diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index eca6eabb..3bb12b15 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -11,17 +11,22 @@ on: jobs: create_release: - runs-on: ubuntu-20.04 # newest available distribution, aka focal + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: # Prevent use of implicit GitHub Actions read-only token GITHUB_TOKEN. We don't deploy on # the tag MAJOR.MINOR.PATCH event, but we still need to deploy the maven-release-plugin master commit. token: ${{ secrets.GH_TOKEN }} fetch-depth: 1 # only need the HEAD commit as license check isn't run + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' # zulu as it supports a wide version range + java-version: '11' # earliest LTS and last that can compile the 1.6 release profile. - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6a9e4fec..1d7ba5f2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,20 +14,29 @@ on: jobs: deploy: - runs-on: ubuntu-20.04 # newest available distribution, aka focal + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: - fetch-depth: 1 # only needed to get the sha label + # Prevent use of implicit GitHub Actions read-only token GITHUB_TOKEN. + # We push Javadocs to the gh-pages branch on commit. + token: ${{ secrets.GH_TOKEN }} + fetch-depth: 0 # allow build-bin/idl_to_gh_pages to get the full history + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' # zulu as it supports a wide version range + java-version: '11' # earliest LTS and last that can compile the 1.6 release profile. - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-maven- - # We can't cache Docker without using buildx because GH actions restricts /var/lib/docker - # That's ok because DOCKER_PARENT_IMAGE is always ghcr.io and local anyway. + # Don't attempt to cache Docker. Sensitive information can be stolen + # via forks, and login session ends up in ~/.docker. This is ok because + # we publish DOCKER_PARENT_IMAGE to ghcr.io, hence local to the runner. - name: Deploy env: # GH_USER= @@ -51,7 +60,7 @@ jobs: # - referenced in .settings.xml SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # DOCKERHUB_USER= - # - only push top-level projects: zipkin zipkin-aws zipkin-dependencies zipkin-aws to Docker Hub, only on release + # - only push top-level projects: zipkin zipkin-aws zipkin-dependencies zipkin-gcp to Docker Hub, only on release # - login like this: echo "$DOCKERHUB_TOKEN"| docker login -u "$DOCKERHUB_USER" --password-stdin DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} # DOCKERHUB_TOKEN= diff --git a/.github/workflows/docker_push.yml b/.github/workflows/docker_push.yml index 64a83bc5..14dd23c9 100644 --- a/.github/workflows/docker_push.yml +++ b/.github/workflows/docker_push.yml @@ -11,14 +11,15 @@ on: jobs: docker_push: - runs-on: ubuntu-20.04 # newest available distribution, aka focal + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 1 # only needed to get the sha label - # We can't cache Docker without using buildx because GH actions restricts /var/lib/docker - # That's ok because DOCKER_PARENT_IMAGE is always ghcr.io and local anyway. + # Don't attempt to cache Docker. Sensitive information can be stolen + # via forks, and login session ends up in ~/.docker. This is ok because + # we publish DOCKER_PARENT_IMAGE to ghcr.io, hence local to the runner. - name: Docker Push run: | # GITHUB_REF will be refs/tags/docker-MAJOR.MINOR.PATCH build-bin/git/login_git && diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 49040c10..472dad6d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,21 +15,58 @@ on: paths-ignore: '**/*.md' jobs: + test-javadoc: + name: Test JavaDoc Builds + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish + if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # full git history for license check + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' # zulu as it supports a wide version range + java-version: '11' # earliest LTS and last that can compile the 1.6 release profile. + - name: Cache local Maven repository + uses: actions/cache@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-jdk-11-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-jdk-11-maven- + - name: Build JavaDoc + run: ./mvnw clean javadoc:aggregate -Prelease + test: - runs-on: ubuntu-20.04 # newest available distribution, aka focal + name: test (JDK ${{ matrix.java_version }}) + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" + strategy: + fail-fast: false # don't fail fast as sometimes failures are operating system specific + matrix: # use latest available versions and be consistent on all workflows! + include: + - java_version: 11 # Last that can compile zipkin core to 1.6 for zipkin-reporter + maven_args: -Prelease -Dgpg.skip -Dmaven.javadoc.skip=true + - java_version: 21 # Most recent LTS steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + fetch-depth: 0 # full git history for license check + - name: Setup java + uses: actions/setup-java@v4 with: - fetch-depth: 0 # full git history for license check + distribution: 'zulu' # zulu as it supports a wide version range + java-version: ${{ matrix.java_version }} - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-maven- - # We can't cache Docker without using buildx because GH actions restricts /var/lib/docker - # That's ok because DOCKER_PARENT_IMAGE is always ghcr.io and local anyway. + key: ${{ runner.os }}-jdk-${{ matrix.java_version }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-jdk-${{ matrix.java_version }}-maven- + # Don't attempt to cache Docker. Sensitive information can be stolen + # via forks, and login session ends up in ~/.docker. This is ok because + # we publish DOCKER_PARENT_IMAGE to ghcr.io, hence local to the runner. - name: Test run: build-bin/configure_test && build-bin/test diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index 2cc7d4a5..cb28b0e3 100644 Binary files a/.mvn/wrapper/maven-wrapper.jar and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 642d572c..346d645f 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,18 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/build-bin/README.md b/build-bin/README.md index a7b407b1..89d3147f 100755 --- a/build-bin/README.md +++ b/build-bin/README.md @@ -8,13 +8,12 @@ configuration settings. [docker-compose-zipkin-gcp.xml] ensures GCP authentication works. It is not run on pull request, as the required secure variable is only available on master push. -[//]: # (Below here should be standard for all projects) ## Build Overview `build-bin` holds portable scripts used in CI to test and deploy the project. The scripts here are portable. They do not include any CI provider-specific logic or ENV variables. -This helps `.travis.yml` and `test.yml` (GitHub Actions) contain nearly the same contents, even if +This helps `test.yml` (GitHub Actions) and alternatives contain nearly the same contents, even if certain OpenZipkin projects need slight adjustments here. Portability has proven necessary, as OpenZipkin has had to transition CI providers many times due to feature and quota constraints. @@ -40,8 +39,8 @@ blank. Tests should not run on documentation-only commits. Tests must not depend resources, as running tests can leak credentials. Git checkouts should include the full history so that license headers or other git analysis can take place. - * [configure_test] - Sets up build environment for tests. - * [test] - Builds and runs tests for this project. +* [configure_test] - Sets up build environment for tests. +* [test] - Builds and runs tests for this project. ### Example GitHub Actions setup @@ -52,9 +51,6 @@ the scripts it uses. The `on:` section obviates job creation and resource usage for irrelevant events. Notably, GitHub Actions includes the ability to skip documentation-only jobs. -Combine [configure_test] and [test] into the same `run:` when `configure_test` primes file system -cache. - Here's a partial `test.yml` including only the aspects mentioned above. ```yaml on: @@ -70,54 +66,13 @@ jobs: test: steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: - fetch-depth: 0 # full git history + fetch-depth: 0 # full git history for license check - name: Test - run: build-bin/configure_test && build-bin/test -``` - -### Example Travis setup -`.travis.yml` is a monolithic configuration file broken into stages, of which the default is "test". -A simplest Travis `test` job configures tests in `install` and runs them as `script`, but only on -relevant event conditions. - -The `if:` section obviates job creation and resource usage for irrelevant events. Travis does not -support file conditions. A `before_install` step to skip documentation-only commits will likely -complete in less than a minute (10 credit cost). - -Here's a partial `.travis.yml` including only the aspects mentioned above. -```yaml -git: - depth: false # TRAVIS_COMMIT_RANGE requires full commit history. - -jobs: - include: - - stage: test - if: branch = master AND tag IS blank AND type IN (push, pull_request) - name: Run unit and integration tests - before_install: | # Prevent test build of a documentation-only change. - if [ -n "${TRAVIS_COMMIT_RANGE}" ] && ! git diff --name-only "${TRAVIS_COMMIT_RANGE}" -- | grep -qv '\.md$'; then - echo "Stopping job as changes only affect documentation (ex. README.md)" - travis_terminate 0 - fi - install: ./build-bin/configure_test - script: ./build-bin/test -``` - -When Travis only runs tests (something else does deploy), there's no need to use stages: -```yaml -git: - depth: false # TRAVIS_COMMIT_RANGE requires full commit history. - -if: branch = master AND tag IS blank AND type IN (push, pull_request) -before_install: | # Prevent test build of a documentation-only change. - if [ -n "${TRAVIS_COMMIT_RANGE}" ] && ! git diff --name-only "${TRAVIS_COMMIT_RANGE}" -- | grep -qv '\.md$'; then - echo "Stopping job as changes only affect documentation (ex. README.md)" - travis_terminate 0 - fi -install: ./build-bin/configure_test -script: ./build-bin/test + run: | + build-bin/configure_test + build-bin/test ``` ## Deploy @@ -127,8 +82,8 @@ providers deploy pushes to master on when the tag is blank, but not on documenta Releases should deploy on version tags (ex `/^[0-9]+\.[0-9]+\.[0-9]+/`), without consideration of if the commit is documentation only or not. - * [configure_deploy] - Sets up environment and logs in, assuming [configure_test] was not called. - * [deploy] - deploys the project, with arg0 being "master" or a release commit like "1.2.3" +* [configure_deploy] - Sets up environment and logs in, assuming [configure_test] was not called. +* [deploy] - deploys the project, with arg0 being "master" or a release commit like "1.2.3" ### Example GitHub Actions setup @@ -140,77 +95,28 @@ The `on:` section obviates job creation and resource usage for irrelevant events cannot implement "master, except documentation only-commits" in the same file. Hence, deployments of master will happen even on README change. -Combine [configure_deploy] and [deploy] into the same `run:` when `configure_deploy` primes file -system cache. - Here's a partial `deploy.yml` including only the aspects mentioned above. Notice env variables are explicitly defined and `on.tags` is a [glob pattern](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet). + ```yaml on: push: - tags: '[0-9]+.[0-9]+.[0-9]+**' # Ex. 8.272.10 or 15.0.1_p9 + tags: '[0-9]+.[0-9]+.[0-9]+**' # e.g. 8.272.10 or 15.0.1_p9 branches: master jobs: deploy: steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 1 # only needed to get the sha label - - name: Deploy + - name: Configure Deploy + run: build-bin/configure_deploy env: GH_USER: ${{ secrets.GH_USER }} GH_TOKEN: ${{ secrets.GH_TOKEN }} - run: | # GITHUB_REF will be refs/heads/master or refs/tags/MAJOR.MINOR.PATCH - build-bin/configure_deploy && - build-bin/deploy $(echo ${GITHUB_REF} | cut -d/ -f 3) -``` - -### Example Travis setup -`.travis.yml` is a monolithic configuration file broken into stages. This means `test` and `deploy` -are in the same file. A simplest Travis `deploy` stage has two jobs: one for master pushes and -another for version tags. These jobs are controlled by event conditions. - -The `if:` section obviates job creation and resource usage for irrelevant events. Travis does not -support file conditions. A `before_install` step to skip documentation-only commits will likely -complete in less than a minute (10 credit cost). - -As billing is by the minute, it is most cost effective to combine test and deploy on master push. - -Here's a partial `.travis.yml` including only the aspects mentioned above. Notice YAML anchors work -in Travis and `tag =~` [condition](https://github.com/travis-ci/travis-conditions) is a regular -expression. -```yaml -git: - depth: false # full git history for license check, and doc-only skipping - -_terminate_if_only_docs: &terminate_if_only_docs | - if [ -n "${TRAVIS_COMMIT_RANGE}" ] && ! git diff --name-only "${TRAVIS_COMMIT_RANGE}" -- | grep -qv '\.md$'; then - echo "Stopping job as changes only affect documentation (ex. README.md)" - travis_terminate 0 - fi - -jobs: - include: - - stage: test - if: branch = master AND tag IS blank AND type IN (push, pull_request) - before_install: *terminate_if_only_docs - install: | - if [ "${TRAVIS_SECURE_ENV_VARS}" = "true" ] && [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - export SHOULD_DEPLOY=true - ./build-bin/configure_deploy - else - export SHOULD_DEPLOY=false - ./build-bin/configure_test - fi - script: - - ./build-bin/test || travis_terminate 1 - - if [ "${SHOULD_DEPLOY}" != "true" ]; then travis_terminate 0; fi - - travis_wait ./build-bin/deploy master - - stage: deploy - # Ex. 8.272.10 or 15.0.1_p9 - if: tag =~ /^[0-9]+\.[0-9]+\.[0-9]+/ AND type = push AND env(GH_TOKEN) IS present - install: ./build-bin/configure_deploy - script: ./build-bin/deploy ${TRAVIS_TAG} + - name: Deploy + # GITHUB_REF will be refs/heads/master or refs/tags/1.2.3 + run: build-bin/deploy $(echo ${GITHUB_REF} | cut -d/ -f 3) ``` diff --git a/build-bin/docker/configure_docker b/build-bin/docker/configure_docker index c34fd03a..d355d8f9 100755 --- a/build-bin/docker/configure_docker +++ b/build-bin/docker/configure_docker @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -25,13 +25,8 @@ set -ue # * checks.disable=true - saves time and a docker.io pull of alpine # * ryuk doesn't count against docker.io rate limits because Docker approved testcontainers as OSS echo checks.disable=true >> ~/.testcontainers.properties -# * upgrade ryuk until https://github.com/testcontainers/testcontainers-java/pull/3630 -echo ryuk.container.image=testcontainers/ryuk:0.3.1 >> ~/.testcontainers.properties # We don't use any docker.io images, but add a Google's mirror in case something implicitly does # * See https://cloud.google.com/container-registry/docs/pulling-cached-images echo '{ "registry-mirrors": ["https://mirror.gcr.io"] }' | sudo tee /etc/docker/daemon.json sudo service docker restart - -# * Ensure buildx and related features are disabled -mkdir -p ${HOME}/.docker && echo '{"experimental":"disabled"}' > ${HOME}/.docker/config.json diff --git a/build-bin/docker/configure_docker_push b/build-bin/docker/configure_docker_push index 4987a67f..0a9451f5 100755 --- a/build-bin/docker/configure_docker_push +++ b/build-bin/docker/configure_docker_push @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -50,5 +50,8 @@ fi # See https://github.com/multiarch/qemu-user-static # # Mirrored image use to avoid docker.io pulls: -# docker tag multiarch/qemu-user-static:5.1.0-7 ghcr.io/openzipkin/multiarch-qemu-user-static:latest +# docker tag multiarch/qemu-user-static:7.2.0-1 ghcr.io/openzipkin/multiarch-qemu-user-static:latest +# +# Note: This image only works on x86_64/amd64 architecture. +# See: https://github.com/multiarch/qemu-user-static#supported-host-architectures docker run --rm --privileged ghcr.io/openzipkin/multiarch-qemu-user-static --reset -p yes diff --git a/build-bin/docker/docker_arch b/build-bin/docker/docker_arch index 29308940..b00f84c0 100755 --- a/build-bin/docker/docker_arch +++ b/build-bin/docker/docker_arch @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -21,6 +21,8 @@ set -ue # Normalize docker_arch to what's available +# +# Note: s390x and ppc64le were added for Knative docker_arch=${DOCKER_ARCH:-$(uname -m)} case ${docker_arch} in amd64* ) @@ -35,6 +37,12 @@ case ${docker_arch} in aarch64* ) docker_arch=arm64 ;; + s390x* ) + docker_arch=s390x + ;; + ppc64le* ) + docker_arch=ppc64le + ;; * ) >&2 echo "Unsupported DOCKER_ARCH: ${docker_arch}" exit 1; diff --git a/build-bin/docker/docker_args b/build-bin/docker/docker_args index 6eb0e153..b5e56cb3 100755 --- a/build-bin/docker/docker_args +++ b/build-bin/docker/docker_args @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -46,7 +46,7 @@ if [ -n "${DOCKER_TARGET}" ]; then fi # When non-empty, becomes the base layer including tag appropriate for the image being built. -# Ex. ghcr.io/openzipkin/java:15.0.1_p9-jre +# e.g. ghcr.io/openzipkin/java:21.0.1_p12-jre # # This is not required to be a base (FROM scratch) image like ghcr.io/openzipkin/alpine:3.12.3 # See https://docs.docker.com/glossary/#parent-image @@ -54,13 +54,13 @@ if [ -n "${DOCKER_PARENT_IMAGE}" ]; then docker_args="${docker_args} --build-arg docker_parent_image=${DOCKER_PARENT_IMAGE}" fi -# When non-empty, becomes the build-arg alpine_version. Ex. "3.12.3" +# When non-empty, becomes the build-arg alpine_version. e.g. "3.12.3" # Used to align base layers from https://github.com/orgs/openzipkin/packages/container/package/alpine if [ -n "${ALPINE_VERSION}" ]; then docker_args="${docker_args} --build-arg alpine_version=${ALPINE_VERSION}" fi -# When non-empty, becomes the build-arg java_version. Ex. "15.0.1_p9" +# When non-empty, becomes the build-arg java_version. e.g. "21.0.1_p12" # Used to align base layers from https://github.com/orgs/openzipkin/packages/container/package/java if [ -n "${JAVA_VERSION}" ]; then docker_args="${docker_args} --build-arg java_version=${JAVA_VERSION}" @@ -69,13 +69,13 @@ if [ -n "${JAVA_VERSION}" ]; then java_major_version=$(echo ${JAVA_VERSION}| cut -f1 -d .) case ${java_major_version} in 8) java_home=/usr/lib/jvm/java-1.8-openjdk;; - 1?) java_home=/usr/lib/jvm/java-${java_major_version}-openjdk;; + 1?|2?|3?) java_home=/usr/lib/jvm/java-${java_major_version}-openjdk;; esac if [ -n "${java_home}" ]; then docker_args="${docker_args} --build-arg java_home=${java_home}"; fi fi -# When non-empty, becomes the build-arg maven_classifier. Ex. "module" or "exec" +# When non-empty, becomes the build-arg maven_classifier. e.g. "module" or "exec" # Used as the classifier arg to ./build-bin/maven/maven_unjar. Allows building two images with the # same Dockerfile, varying on classifier, like openzipkin/zipkin vs openzipkin/zipkin-slim if [ -n "${MAVEN_CLASSIFIER}" ]; then diff --git a/build-bin/docker/docker_block_on_health b/build-bin/docker/docker_block_on_health index f45da42b..c7b135f2 100755 --- a/build-bin/docker/docker_block_on_health +++ b/build-bin/docker/docker_block_on_health @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/docker/docker_build b/build-bin/docker/docker_build index e10f7aed..d7a33157 100755 --- a/build-bin/docker/docker_build +++ b/build-bin/docker/docker_build @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2021 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -19,9 +19,10 @@ docker_tag=${1?full docker_tag is required. Ex openzipkin/zipkin:test} version=${2:-} docker_args=$($(dirname "$0")/docker_args ${version}) -# Avoid buildx on load for reasons including: -# * Caching is more complex as builder instances must be considered -# * It only supports one platform/arch on load https://github.com/docker/buildx/issues/59 -# * It would pull Docker Hub for moby/buildkit or multiarch/qemu-user-static images, using up quota +# We don't need build kit, but Docker 20.10 no longer accepts --platform +# without it. It is simpler to always enable it vs require maintainers to use +# alternate OCI tools. See https://github.com/moby/moby/issues/41552 +export DOCKER_BUILDKIT=1 + echo "Building image ${docker_tag}" -DOCKER_BUILDKIT=1 docker build --pull ${docker_args} --tag ${docker_tag} . +docker build --network=host --pull ${docker_args} --tag ${docker_tag} . diff --git a/build-bin/docker/docker_push b/build-bin/docker/docker_push index 9a9fe12a..a3c4b77a 100755 --- a/build-bin/docker/docker_push +++ b/build-bin/docker/docker_push @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2021 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -27,8 +27,10 @@ set -ue docker_image=${1?docker_image is required, notably without a tag. Ex openzipkin/zipkin} version=${2:-master} -# We don't need build kit, but Docker 20.10 no longer accepts --platform without it. -# It is simpler to just always enable it. See https://github.com/moby/moby/issues/41552 + +# We don't need build kit, but Docker 20.10 no longer accepts --platform +# without it. It is simpler to always enable it vs require maintainers to use +# alternate OCI tools. See https://github.com/moby/moby/issues/41552 export DOCKER_BUILDKIT=1 case ${version} in @@ -66,7 +68,8 @@ for repo in ${docker_repos}; do done docker_args=$($(dirname "$0")/docker_args ${version}) -docker_archs=${DOCKER_ARCHS:-amd64 arm64} +# Note: s390x and ppc64le were added for Knative +docker_archs=${DOCKER_ARCHS:-amd64 arm64 s390x ppc64le} echo "Will build the following architectures: ${docker_archs}" @@ -116,4 +119,3 @@ else docker manifest push -p ${tag} done fi - diff --git a/build-bin/docker/docker_test_image b/build-bin/docker/docker_test_image index 54e7ae21..0378ab95 100755 --- a/build-bin/docker/docker_test_image +++ b/build-bin/docker/docker_test_image @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/git/login_git b/build-bin/git/login_git index 825e8490..4ca78506 100755 --- a/build-bin/git/login_git +++ b/build-bin/git/login_git @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/git/version_from_trigger_tag b/build-bin/git/version_from_trigger_tag index 5534d40c..a6875f0d 100755 --- a/build-bin/git/version_from_trigger_tag +++ b/build-bin/git/version_from_trigger_tag @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/gpg/configure_gpg b/build-bin/gpg/configure_gpg index 4854f5d2..8049504d 100755 --- a/build-bin/gpg/configure_gpg +++ b/build-bin/gpg/configure_gpg @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_build b/build-bin/maven/maven_build index 5183fb77..5c65c6fe 100755 --- a/build-bin/maven/maven_build +++ b/build-bin/maven/maven_build @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_build_or_unjar b/build-bin/maven/maven_build_or_unjar index e1c31b7c..eeadf5d7 100755 --- a/build-bin/maven/maven_build_or_unjar +++ b/build-bin/maven/maven_build_or_unjar @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_deploy b/build-bin/maven/maven_deploy index b43578ed..12f73244 100755 --- a/build-bin/maven/maven_deploy +++ b/build-bin/maven/maven_deploy @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_go_offline b/build-bin/maven/maven_go_offline index d8cc8582..57c86cd0 100755 --- a/build-bin/maven/maven_go_offline +++ b/build-bin/maven/maven_go_offline @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_opts b/build-bin/maven/maven_opts index 0bf0670d..2ba40b3b 100755 --- a/build-bin/maven/maven_opts +++ b/build-bin/maven/maven_opts @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_release b/build-bin/maven/maven_release index 8c8446ec..d4122b68 100755 --- a/build-bin/maven/maven_release +++ b/build-bin/maven/maven_release @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at diff --git a/build-bin/maven/maven_unjar b/build-bin/maven/maven_unjar index bf2643db..2e94113b 100755 --- a/build-bin/maven/maven_unjar +++ b/build-bin/maven/maven_unjar @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright 2016-2020 The OpenZipkin Authors +# Copyright 2016-2023 The OpenZipkin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -67,7 +67,7 @@ fi if ! test -f ${artifact_id}.jar && [ ${is_release} = "true" ]; then mvn_get="mvn -q --batch-mode -Denforcer.fail=false \ - org.apache.maven.plugins:maven-dependency-plugin:3.1.2:get \ + org.apache.maven.plugins:maven-dependency-plugin:3.6.1:get \ -Dtransitive=false -DgroupId=${group_id} -DartifactId=${artifact_id} -Dversion=${version}" if [ -n "${classifier}" ]; then diff --git a/collector-pubsub/pom.xml b/collector-pubsub/pom.xml index 74522545..d1bbbc67 100644 --- a/collector-pubsub/pom.xml +++ b/collector-pubsub/pom.xml @@ -1,7 +1,7 @@ - - zipkin-gcp-parent - io.zipkin.gcp - 1.0.3-SNAPSHOT - - 4.0.0 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + zipkin-gcp-parent + io.zipkin.gcp + 1.0.5-SNAPSHOT + + 4.0.0 - collector-pubsub + collector-pubsub - - ${project.basedir}/.. - + + ${project.basedir}/.. + - - - - com.google.cloud - libraries-bom - 24.1.2 - pom - import - - - - - - - com.google.cloud - google-cloud-pubsub - - - io.zipkin.zipkin2 - zipkin-collector - ${zipkin.version} - - - io.grpc - grpc-testing - 1.43.2 - test - - - com.google.api.grpc - grpc-google-cloud-pubsub-v1 - 1.97.1 - test - - - org.awaitility - awaitility - ${awaitility.version} - test - - + + + io.zipkin.zipkin2 + zipkin-collector + ${zipkin.version} + + + com.google.cloud + google-cloud-pubsub + ${google-cloud-pubsub.version} + + + ${zipkin.groupId} + zipkin-tests + ${zipkin.version} + test + + + com.asarkar.grpc + grpc-test + test + + + com.google.api.grpc + grpc-google-cloud-pubsub-v1 + ${grpc-google-cloud-pubsub-v1.version} + test + + + org.awaitility + awaitility + ${awaitility.version} + test + + \ No newline at end of file diff --git a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/PubSubCollector.java b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/PubSubCollector.java index 0c818406..3db4f7a6 100644 --- a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/PubSubCollector.java +++ b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/PubSubCollector.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,13 +13,11 @@ */ package zipkin2.collector.pubsub; -import java.io.IOException; - import com.google.api.gax.core.ExecutorProvider; import com.google.api.gax.rpc.ApiException; import com.google.cloud.pubsub.v1.Subscriber; import com.google.cloud.pubsub.v1.SubscriptionAdminClient; - +import java.io.IOException; import zipkin2.CheckResult; import zipkin2.codec.Encoding; import zipkin2.collector.Collector; @@ -30,147 +28,151 @@ public class PubSubCollector extends CollectorComponent { - public static final class Builder extends CollectorComponent.Builder { - - String subscription; - Encoding encoding = Encoding.JSON; - ExecutorProvider executorProvider; - SubscriptionAdminClient subscriptionAdminClient; - SubscriberSettings subscriberSettings; - - Collector.Builder delegate = Collector.newBuilder(PubSubCollector.class); - CollectorMetrics metrics = CollectorMetrics.NOOP_METRICS; - - public Builder(PubSubCollector pubSubCollector) { - this.subscription = pubSubCollector.subscription; - this.encoding = pubSubCollector.encoding; - this.executorProvider = pubSubCollector.executorProvider; - } - - @Override - public Builder storage(StorageComponent storageComponent) { - delegate.storage(storageComponent); - return this; - } - - @Override - public Builder metrics(CollectorMetrics metrics) { - if (metrics == null) throw new NullPointerException("metrics == null"); - delegate.metrics(this.metrics = metrics.forTransport("pubsub")); - return this; - } - - @Override - public Builder sampler(CollectorSampler collectorSampler) { - delegate.sampler(collectorSampler); - return this; - } - - /** PubSub subscription to receive spans. */ - public Builder subscription(String subscription) { - if (subscription == null) throw new NullPointerException("subscription == null"); - this.subscription = subscription; - return this; - } - - /** - * Use this to change the encoding used in messages. Default is {@linkplain Encoding#JSON} - * - *

Note: If ultimately sending to Zipkin, version 2.8+ is required to process protobuf. - */ - public Builder encoding(Encoding encoding) { - if (encoding == null) throw new NullPointerException("encoding == null"); - this.encoding = encoding; - return this; - } - - /** ExecutorProvider for PubSub operations **/ - public Builder executorProvider(ExecutorProvider executorProvider) { - if (executorProvider == null) throw new NullPointerException("executorProvider == null"); - this.executorProvider = executorProvider; - return this; - } - - public Builder subscriptionAdminClient(SubscriptionAdminClient subscriptionAdminClient) { - if (subscriptionAdminClient == null) throw new NullPointerException("subscriptionAdminClient == null"); - this.subscriptionAdminClient = subscriptionAdminClient; - return this; - } - - public Builder subscriberSettings(SubscriberSettings subscriberSettings) { - if (subscriberSettings == null) throw new NullPointerException("subscriberSettings == null"); - this.subscriberSettings = subscriberSettings; - return this; - } - - @Override - public PubSubCollector build() { - return new PubSubCollector(this); - } - - Builder() {} - } + public static final class Builder extends CollectorComponent.Builder { + + String subscription; + Encoding encoding = Encoding.JSON; + ExecutorProvider executorProvider; + SubscriptionAdminClient subscriptionAdminClient; + SubscriberSettings subscriberSettings; - final Collector collector; - final CollectorMetrics metrics; - final String subscription; - final Encoding encoding; - Subscriber subscriber; - final ExecutorProvider executorProvider; - final SubscriptionAdminClient subscriptionAdminClient; - final SubscriberSettings subscriberSettings; - - PubSubCollector(Builder builder) { - this.collector = builder.delegate.build(); - this.metrics = builder.metrics; - this.subscription = builder.subscription; - this.encoding = builder.encoding; - this.executorProvider = builder.executorProvider; - this.subscriptionAdminClient = builder.subscriptionAdminClient; - this.subscriberSettings = builder.subscriberSettings; + Collector.Builder delegate = Collector.newBuilder(PubSubCollector.class); + CollectorMetrics metrics = CollectorMetrics.NOOP_METRICS; + + public Builder(PubSubCollector pubSubCollector) { + this.subscription = pubSubCollector.subscription; + this.encoding = pubSubCollector.encoding; + this.executorProvider = pubSubCollector.executorProvider; } @Override - public CollectorComponent start() { - Subscriber.Builder builder = Subscriber.newBuilder(subscription, new SpanMessageReceiver(collector, metrics)); - subscriber = applyConfigurations(builder).build(); - subscriber.startAsync().awaitRunning(); - return this; + public Builder storage(StorageComponent storageComponent) { + delegate.storage(storageComponent); + return this; } - private Subscriber.Builder applyConfigurations(Subscriber.Builder builder) { - if(subscriberSettings==null) { - return builder; - } - - subscriberSettings.getChannelProvider().ifPresent(builder::setChannelProvider); - subscriberSettings.getHeaderProvider().ifPresent(builder::setHeaderProvider); - subscriberSettings.getFlowControlSettings().ifPresent(builder::setFlowControlSettings); - builder.setUseLegacyFlowControl(subscriberSettings.isUseLegacyFlowControl()); - subscriberSettings.getMaxAckExtensionPeriod().ifPresent(builder::setMaxAckExtensionPeriod); - subscriberSettings.getMaxDurationPerAckExtension().ifPresent(builder::setMaxDurationPerAckExtension); - subscriberSettings.getExecutorProvider().ifPresent(builder::setExecutorProvider); - subscriberSettings.getCredentialsProvider().ifPresent(builder::setCredentialsProvider); - subscriberSettings.getSystemExecutorProvider().ifPresent(builder::setSystemExecutorProvider); - builder.setParallelPullCount(subscriberSettings.getParallelPullCount()); - subscriberSettings.getEndpoint().ifPresent(builder::setEndpoint); - - return builder; + @Override + public Builder metrics(CollectorMetrics metrics) { + if (metrics == null) throw new NullPointerException("metrics == null"); + delegate.metrics(this.metrics = metrics.forTransport("pubsub")); + return this; } @Override - public CheckResult check() { - try { - subscriptionAdminClient.getSubscription(subscription); - return CheckResult.OK; - } catch (ApiException e) { - return CheckResult.failed(e); - } + public Builder sampler(CollectorSampler collectorSampler) { + delegate.sampler(collectorSampler); + return this; + } + + /** PubSub subscription to receive spans. */ + public Builder subscription(String subscription) { + if (subscription == null) throw new NullPointerException("subscription == null"); + this.subscription = subscription; + return this; + } + + /** + * Use this to change the encoding used in messages. Default is {@linkplain Encoding#JSON} + * + *

Note: If ultimately sending to Zipkin, version 2.8+ is required to process protobuf. + */ + public Builder encoding(Encoding encoding) { + if (encoding == null) throw new NullPointerException("encoding == null"); + this.encoding = encoding; + return this; + } + + /** ExecutorProvider for PubSub operations **/ + public Builder executorProvider(ExecutorProvider executorProvider) { + if (executorProvider == null) throw new NullPointerException("executorProvider == null"); + this.executorProvider = executorProvider; + return this; + } + + public Builder subscriptionAdminClient(SubscriptionAdminClient subscriptionAdminClient) { + if (subscriptionAdminClient == null) { + throw new NullPointerException("subscriptionAdminClient == null"); + } + this.subscriptionAdminClient = subscriptionAdminClient; + return this; + } + + public Builder subscriberSettings(SubscriberSettings subscriberSettings) { + if (subscriberSettings == null) throw new NullPointerException("subscriberSettings == null"); + this.subscriberSettings = subscriberSettings; + return this; } @Override - public void close() throws IOException { - subscriber.stopAsync().awaitTerminated(); + public PubSubCollector build() { + return new PubSubCollector(this); + } + + Builder() { + } + } + + final Collector collector; + final CollectorMetrics metrics; + final String subscription; + final Encoding encoding; + Subscriber subscriber; + final ExecutorProvider executorProvider; + final SubscriptionAdminClient subscriptionAdminClient; + final SubscriberSettings subscriberSettings; + + PubSubCollector(Builder builder) { + this.collector = builder.delegate.build(); + this.metrics = builder.metrics; + this.subscription = builder.subscription; + this.encoding = builder.encoding; + this.executorProvider = builder.executorProvider; + this.subscriptionAdminClient = builder.subscriptionAdminClient; + this.subscriberSettings = builder.subscriberSettings; + } + + @Override + public CollectorComponent start() { + Subscriber.Builder builder = + Subscriber.newBuilder(subscription, new SpanMessageReceiver(collector, metrics)); + subscriber = applyConfigurations(builder).build(); + subscriber.startAsync().awaitRunning(); + return this; + } + + private Subscriber.Builder applyConfigurations(Subscriber.Builder builder) { + if (subscriberSettings == null) { + return builder; + } + + subscriberSettings.getChannelProvider().ifPresent(builder::setChannelProvider); + subscriberSettings.getHeaderProvider().ifPresent(builder::setHeaderProvider); + subscriberSettings.getFlowControlSettings().ifPresent(builder::setFlowControlSettings); + builder.setUseLegacyFlowControl(subscriberSettings.isUseLegacyFlowControl()); + subscriberSettings.getMaxAckExtensionPeriod().ifPresent(builder::setMaxAckExtensionPeriod); + subscriberSettings.getMaxDurationPerAckExtension() + .ifPresent(builder::setMaxDurationPerAckExtension); + subscriberSettings.getExecutorProvider().ifPresent(builder::setExecutorProvider); + subscriberSettings.getCredentialsProvider().ifPresent(builder::setCredentialsProvider); + subscriberSettings.getSystemExecutorProvider().ifPresent(builder::setSystemExecutorProvider); + builder.setParallelPullCount(subscriberSettings.getParallelPullCount()); + subscriberSettings.getEndpoint().ifPresent(builder::setEndpoint); + + return builder; + } + + @Override + public CheckResult check() { + try { + subscriptionAdminClient.getSubscription(subscription); + return CheckResult.OK; + } catch (ApiException e) { + return CheckResult.failed(e); } + } + @Override + public void close() throws IOException { + subscriber.stopAsync().awaitTerminated(); + } } diff --git a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanCallback.java b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanCallback.java index 2a6fea41..b8bd85cd 100644 --- a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanCallback.java +++ b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -14,25 +14,23 @@ package zipkin2.collector.pubsub; import com.google.cloud.pubsub.v1.AckReplyConsumer; - import zipkin2.Callback; final class SpanCallback implements Callback { - private final AckReplyConsumer ackReplyConsumer; - - public SpanCallback(AckReplyConsumer ackReplyConsumer) { - this.ackReplyConsumer = ackReplyConsumer; - } + private final AckReplyConsumer ackReplyConsumer; - @Override - public void onSuccess(Void value) { - ackReplyConsumer.ack(); - } + public SpanCallback(AckReplyConsumer ackReplyConsumer) { + this.ackReplyConsumer = ackReplyConsumer; + } - @Override - public void onError(Throwable throwable) { - ackReplyConsumer.nack(); - } + @Override + public void onSuccess(Void value) { + ackReplyConsumer.ack(); + } + @Override + public void onError(Throwable throwable) { + ackReplyConsumer.nack(); + } } diff --git a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanMessageReceiver.java b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanMessageReceiver.java index 7b3f02d7..232fc2cb 100644 --- a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanMessageReceiver.java +++ b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SpanMessageReceiver.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -16,26 +16,24 @@ import com.google.cloud.pubsub.v1.AckReplyConsumer; import com.google.cloud.pubsub.v1.MessageReceiver; import com.google.pubsub.v1.PubsubMessage; - import zipkin2.collector.Collector; import zipkin2.collector.CollectorMetrics; final class SpanMessageReceiver implements MessageReceiver { - final Collector collector; - final CollectorMetrics metrics; - - public SpanMessageReceiver(Collector collector, CollectorMetrics metrics) { - this.collector = collector; - this.metrics = metrics; - } + final Collector collector; + final CollectorMetrics metrics; - @Override - public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer ackReplyConsumer) { - byte[] serialized = pubsubMessage.getData().toByteArray(); - metrics.incrementMessages(); - metrics.incrementBytes(serialized.length); - collector.acceptSpans(serialized, new SpanCallback(ackReplyConsumer)); - } + public SpanMessageReceiver(Collector collector, CollectorMetrics metrics) { + this.collector = collector; + this.metrics = metrics; + } + @Override + public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer ackReplyConsumer) { + byte[] serialized = pubsubMessage.getData().toByteArray(); + metrics.incrementMessages(); + metrics.incrementBytes(serialized.length); + collector.acceptSpans(serialized, new SpanCallback(ackReplyConsumer)); + } } diff --git a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SubscriberSettings.java b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SubscriberSettings.java index 12518080..28eebc38 100644 --- a/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SubscriberSettings.java +++ b/collector-pubsub/src/main/java/zipkin2/collector/pubsub/SubscriberSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,117 +13,113 @@ */ package zipkin2.collector.pubsub; -import java.util.Optional; - -import org.threeten.bp.Duration; - -import com.google.api.core.ApiClock; import com.google.api.gax.batching.FlowControlSettings; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.ExecutorProvider; import com.google.api.gax.rpc.HeaderProvider; import com.google.api.gax.rpc.TransportChannelProvider; +import java.util.Optional; +import org.threeten.bp.Duration; public class SubscriberSettings { - private Optional channelProvider = Optional.empty(); - private Optional headerProvider = Optional.empty(); - private Optional flowControlSettings = Optional.empty(); - private boolean useLegacyFlowControl = false; - private Optional maxAckExtensionPeriod = Optional.empty(); - private Optional maxDurationPerAckExtension = Optional.empty(); - private Optional executorProvider = Optional.empty(); - private Optional credentialsProvider = Optional.empty(); - private Optional systemExecutorProvider = Optional.empty(); - private int parallelPullCount = 1; - private Optional endpoint = Optional.empty(); - - public Optional getChannelProvider() { - return channelProvider; - } - - public void setChannelProvider(TransportChannelProvider channelProvider) { - this.channelProvider = Optional.of(channelProvider); - } - - public Optional getHeaderProvider() { - return headerProvider; - } - - public void setHeaderProvider(HeaderProvider headerProvider) { - this.headerProvider = Optional.of(headerProvider); - } - - public Optional getFlowControlSettings() { - return flowControlSettings; - } - - public void setFlowControlSettings(FlowControlSettings flowControlSettings) { - this.flowControlSettings = Optional.of(flowControlSettings); - } - - public boolean isUseLegacyFlowControl() { - return useLegacyFlowControl; - } - - public void setUseLegacyFlowControl(boolean useLegacyFlowControl) { - this.useLegacyFlowControl = useLegacyFlowControl; - } - - public Optional getMaxAckExtensionPeriod() { - return maxAckExtensionPeriod; - } - - public void setMaxAckExtensionPeriod(Duration maxAckExtensionPeriod) { - this.maxAckExtensionPeriod = Optional.of(maxAckExtensionPeriod); - } - - public Optional getMaxDurationPerAckExtension() { - return maxDurationPerAckExtension; - } - - public void setMaxDurationPerAckExtension(Duration maxDurationPerAckExtension) { - this.maxDurationPerAckExtension = Optional.of(maxDurationPerAckExtension); - } - - public Optional getExecutorProvider() { - return executorProvider; - } - - public void setExecutorProvider(ExecutorProvider executorProvider) { - this.executorProvider = Optional.of(executorProvider); - } - - public Optional getCredentialsProvider() { - return credentialsProvider; - } - - public void setCredentialsProvider(CredentialsProvider credentialsProvider) { - this.credentialsProvider = Optional.of(credentialsProvider); - } - - public Optional getSystemExecutorProvider() { - return systemExecutorProvider; - } - - public void setSystemExecutorProvider(ExecutorProvider systemExecutorProvider) { - this.systemExecutorProvider = Optional.of(systemExecutorProvider); - } - - public int getParallelPullCount() { - return parallelPullCount; - } - - public void setParallelPullCount(int parallelPullCount) { - this.parallelPullCount = parallelPullCount; - } - - public Optional getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = Optional.of(endpoint); - } - + private Optional channelProvider = Optional.empty(); + private Optional headerProvider = Optional.empty(); + private Optional flowControlSettings = Optional.empty(); + private boolean useLegacyFlowControl = false; + private Optional maxAckExtensionPeriod = Optional.empty(); + private Optional maxDurationPerAckExtension = Optional.empty(); + private Optional executorProvider = Optional.empty(); + private Optional credentialsProvider = Optional.empty(); + private Optional systemExecutorProvider = Optional.empty(); + private int parallelPullCount = 1; + private Optional endpoint = Optional.empty(); + + public Optional getChannelProvider() { + return channelProvider; + } + + public void setChannelProvider(TransportChannelProvider channelProvider) { + this.channelProvider = Optional.of(channelProvider); + } + + public Optional getHeaderProvider() { + return headerProvider; + } + + public void setHeaderProvider(HeaderProvider headerProvider) { + this.headerProvider = Optional.of(headerProvider); + } + + public Optional getFlowControlSettings() { + return flowControlSettings; + } + + public void setFlowControlSettings(FlowControlSettings flowControlSettings) { + this.flowControlSettings = Optional.of(flowControlSettings); + } + + public boolean isUseLegacyFlowControl() { + return useLegacyFlowControl; + } + + public void setUseLegacyFlowControl(boolean useLegacyFlowControl) { + this.useLegacyFlowControl = useLegacyFlowControl; + } + + public Optional getMaxAckExtensionPeriod() { + return maxAckExtensionPeriod; + } + + public void setMaxAckExtensionPeriod(Duration maxAckExtensionPeriod) { + this.maxAckExtensionPeriod = Optional.of(maxAckExtensionPeriod); + } + + public Optional getMaxDurationPerAckExtension() { + return maxDurationPerAckExtension; + } + + public void setMaxDurationPerAckExtension(Duration maxDurationPerAckExtension) { + this.maxDurationPerAckExtension = Optional.of(maxDurationPerAckExtension); + } + + public Optional getExecutorProvider() { + return executorProvider; + } + + public void setExecutorProvider(ExecutorProvider executorProvider) { + this.executorProvider = Optional.of(executorProvider); + } + + public Optional getCredentialsProvider() { + return credentialsProvider; + } + + public void setCredentialsProvider(CredentialsProvider credentialsProvider) { + this.credentialsProvider = Optional.of(credentialsProvider); + } + + public Optional getSystemExecutorProvider() { + return systemExecutorProvider; + } + + public void setSystemExecutorProvider(ExecutorProvider systemExecutorProvider) { + this.systemExecutorProvider = Optional.of(systemExecutorProvider); + } + + public int getParallelPullCount() { + return parallelPullCount; + } + + public void setParallelPullCount(int parallelPullCount) { + this.parallelPullCount = parallelPullCount; + } + + public Optional getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = Optional.of(endpoint); + } } diff --git a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/PubSubCollectorTest.java b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/PubSubCollectorTest.java index f1b90f88..a927448e 100644 --- a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/PubSubCollectorTest.java +++ b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/PubSubCollectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,120 +13,120 @@ */ package zipkin2.collector.pubsub; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - +import com.asarkar.grpc.test.GrpcCleanupExtension; +import com.asarkar.grpc.test.Resources; import com.google.api.gax.batching.FlowControlSettings; import com.google.api.gax.core.ExecutorProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; +import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.rpc.FixedTransportChannelProvider; import com.google.api.gax.rpc.TransportChannel; import com.google.api.gax.rpc.TransportChannelProvider; - import io.grpc.ManagedChannel; +import io.grpc.Server; import io.grpc.inprocess.InProcessChannelBuilder; import io.grpc.inprocess.InProcessServerBuilder; -import io.grpc.testing.GrpcCleanupRule; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; +import java.io.IOException; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import zipkin2.Span; -import static zipkin2.TestObjects.CLIENT_SPAN; -import static zipkin2.TestObjects.LOTS_OF_SPANS; import zipkin2.codec.Encoding; import zipkin2.collector.CollectorComponent; import zipkin2.collector.InMemoryCollectorMetrics; import zipkin2.storage.InMemoryStorage; -public class PubSubCollectorTest { - - @Rule - public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); - - private InMemoryStorage store; - private InMemoryCollectorMetrics metrics; - private CollectorComponent collector; - - private QueueBasedSubscriberImpl subImplTest = new QueueBasedSubscriberImpl(); - - @Before - public void setup() throws IOException { - - String serverName = InProcessServerBuilder.generateName(); - - grpcCleanup.register(InProcessServerBuilder - .forName(serverName).directExecutor().addService(subImplTest).build().start()); - ExecutorProvider executorProvider = testExecutorProvider(); - - ManagedChannel managedChannel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); - - TransportChannel transportChannel = GrpcTransportChannel.create(managedChannel); - TransportChannelProvider transportChannelProvider = FixedTransportChannelProvider.create(transportChannel); - - - store = InMemoryStorage.newBuilder().build(); - metrics = new InMemoryCollectorMetrics(); - - SubscriberSettings subscriberSettings = new SubscriberSettings(); - subscriberSettings.setChannelProvider(transportChannelProvider); - subscriberSettings.setExecutorProvider(executorProvider); - subscriberSettings.setFlowControlSettings(FlowControlSettings.newBuilder().setMaxOutstandingElementCount(1000l).build()); - - - collector = new PubSubCollector.Builder() - .subscription("projects/test-project/topics/test-subscription") - .storage(store) - .encoding(Encoding.JSON) - .executorProvider(executorProvider) - .subscriberSettings(subscriberSettings) - .metrics(metrics) - .build() - .start(); - metrics = metrics.forTransport("pubsub"); - } - - @Test - public void collectSpans() throws Exception { - List spans = Arrays.asList(LOTS_OF_SPANS[0], LOTS_OF_SPANS[1], LOTS_OF_SPANS[2]); - subImplTest.addSpans(spans); - assertSpansAccepted(spans); - } - - @Test - public void testNow() { - subImplTest.addSpan(CLIENT_SPAN); - await().atMost(10, TimeUnit.SECONDS).until(() -> store.acceptedSpanCount() == 1); - } - - @After - public void teardown() throws IOException, InterruptedException { - store.close(); - collector.close(); - } - - private InstantiatingExecutorProvider testExecutorProvider() { - return InstantiatingExecutorProvider.newBuilder() - .setExecutorThreadCount(5 * Runtime.getRuntime().availableProcessors()) - .build(); - } - - void assertSpansAccepted(List spans) throws Exception { - await().atMost(20, TimeUnit.SECONDS).until(() -> store.acceptedSpanCount() == 3); - - List someSpans = store.spanStore().getTrace(spans.get(0).traceId()).execute(); - - assertThat(metrics.messages()).as("check accept metrics.").isPositive(); - assertThat(metrics.bytes()).as("check bytes metrics.").isPositive(); - assertThat(metrics.messagesDropped()).as("check dropped metrics.").isEqualTo(0); - assertThat(someSpans).as("recorded spans should not be null").isNotNull(); - assertThat(spans).as("some spans have been recorded").containsAll(someSpans); - } +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static zipkin2.TestObjects.CLIENT_SPAN; +import static zipkin2.TestObjects.LOTS_OF_SPANS; +@ExtendWith(GrpcCleanupExtension.class) +class PubSubCollectorTest { + private InMemoryStorage store; + private InMemoryCollectorMetrics metrics; + private CollectorComponent collector; + + private QueueBasedSubscriberImpl subImplTest = new QueueBasedSubscriberImpl(); + + @BeforeEach void initCollector(Resources resources) throws IOException { + String serverName = InProcessServerBuilder.generateName(); + + Server server = InProcessServerBuilder + .forName(serverName) + .directExecutor() + .addService(subImplTest) + .build().start(); + resources.register(server, Duration.ofSeconds(10)); // shutdown deadline + + ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + resources.register(channel, Duration.ofSeconds(10));// close deadline + + TransportChannel transportChannel = GrpcTransportChannel.create(channel); + TransportChannelProvider transportChannelProvider = + FixedTransportChannelProvider.create(transportChannel); + + ExecutorProvider executorProvider = testExecutorProvider(); + + store = InMemoryStorage.newBuilder().build(); + metrics = new InMemoryCollectorMetrics(); + + SubscriberSettings subscriberSettings = new SubscriberSettings(); + subscriberSettings.setChannelProvider(transportChannelProvider); + subscriberSettings.setExecutorProvider(executorProvider); + subscriberSettings.setCredentialsProvider(new NoCredentialsProvider()); + subscriberSettings.setFlowControlSettings( + FlowControlSettings.newBuilder().setMaxOutstandingElementCount(1000L).build()); + + collector = new PubSubCollector.Builder() + .subscription("projects/test-project/topics/test-subscription") + .storage(store) + .encoding(Encoding.JSON) + .executorProvider(executorProvider) + .subscriberSettings(subscriberSettings) + .metrics(metrics) + .build() + .start(); + metrics = metrics.forTransport("pubsub"); + } + + @Test void collectSpans() throws Exception { + List spans = Arrays.asList(LOTS_OF_SPANS[0], LOTS_OF_SPANS[1], LOTS_OF_SPANS[2]); + subImplTest.addSpans(spans); + assertSpansAccepted(spans); + } + + @Test void testNow() { + subImplTest.addSpan(CLIENT_SPAN); + await().atMost(10, TimeUnit.SECONDS).until(() -> store.acceptedSpanCount() == 1); + } + + @AfterEach void teardown() throws Exception { + store.close(); + collector.close(); + } + + private InstantiatingExecutorProvider testExecutorProvider() { + return InstantiatingExecutorProvider.newBuilder() + .setExecutorThreadCount(5 * Runtime.getRuntime().availableProcessors()) + .build(); + } + + void assertSpansAccepted(List spans) throws Exception { + await().atMost(20, TimeUnit.SECONDS).until(() -> store.acceptedSpanCount() == 3); + + List someSpans = store.spanStore().getTrace(spans.get(0).traceId()).execute(); + + assertThat(metrics.messages()).as("check accept metrics.").isPositive(); + assertThat(metrics.bytes()).as("check bytes metrics.").isPositive(); + assertThat(metrics.messagesDropped()).as("check dropped metrics.").isEqualTo(0); + assertThat(someSpans).as("recorded spans should not be null").isNotNull(); + assertThat(spans).as("some spans have been recorded").containsAll(someSpans); + } } \ No newline at end of file diff --git a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/QueueBasedSubscriberImpl.java b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/QueueBasedSubscriberImpl.java index 4ad71953..1cdf2be6 100644 --- a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/QueueBasedSubscriberImpl.java +++ b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/QueueBasedSubscriberImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,55 +13,46 @@ */ package zipkin2.collector.pubsub; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingDeque; - -import com.google.protobuf.ByteString; import com.google.protobuf.Empty; import com.google.pubsub.v1.AcknowledgeRequest; import com.google.pubsub.v1.ModifyAckDeadlineRequest; -import com.google.pubsub.v1.PubsubMessage; -import com.google.pubsub.v1.PullRequest; -import com.google.pubsub.v1.PullResponse; -import com.google.pubsub.v1.ReceivedMessage; import com.google.pubsub.v1.StreamingPullRequest; import com.google.pubsub.v1.StreamingPullResponse; import com.google.pubsub.v1.SubscriberGrpc; - -import io.grpc.Status; import io.grpc.stub.StreamObserver; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; import zipkin2.Span; -import zipkin2.codec.SpanBytesEncoder; public class QueueBasedSubscriberImpl extends SubscriberGrpc.SubscriberImplBase { - private final BlockingQueue spanQueue = new LinkedBlockingDeque<>(); - - @Override - public StreamObserver streamingPull(StreamObserver responseObserver) { - return new StreamingPullStreamObserver(spanQueue, responseObserver); - } - - public void addSpans(List spans) { - spans.forEach(this::addSpan); - } - - public void addSpan(Span span) { - spanQueue.add(span); - } - - @Override - public void acknowledge(AcknowledgeRequest request, StreamObserver responseObserver) { - responseObserver.onNext(Empty.getDefaultInstance()); - responseObserver.onCompleted(); - } - - @Override - public void modifyAckDeadline(ModifyAckDeadlineRequest request, StreamObserver responseObserver) { - responseObserver.onNext(Empty.getDefaultInstance()); - responseObserver.onCompleted(); - } - + private final BlockingQueue spanQueue = new LinkedBlockingDeque<>(); + + @Override + public StreamObserver streamingPull( + StreamObserver responseObserver) { + return new StreamingPullStreamObserver(spanQueue, responseObserver); + } + + public void addSpans(List spans) { + spans.forEach(this::addSpan); + } + + public void addSpan(Span span) { + spanQueue.add(span); + } + + @Override + public void acknowledge(AcknowledgeRequest request, StreamObserver responseObserver) { + responseObserver.onNext(Empty.getDefaultInstance()); + responseObserver.onCompleted(); + } + + @Override + public void modifyAckDeadline(ModifyAckDeadlineRequest request, + StreamObserver responseObserver) { + responseObserver.onNext(Empty.getDefaultInstance()); + responseObserver.onCompleted(); + } } diff --git a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/StreamingPullStreamObserver.java b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/StreamingPullStreamObserver.java index 3844a79b..411681af 100644 --- a/collector-pubsub/src/test/java/zipkin2/collector/pubsub/StreamingPullStreamObserver.java +++ b/collector-pubsub/src/test/java/zipkin2/collector/pubsub/StreamingPullStreamObserver.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,90 +13,92 @@ */ package zipkin2.collector.pubsub; -import java.util.Collections; -import java.util.UUID; -import java.util.concurrent.BlockingQueue; - import com.google.common.util.concurrent.AbstractExecutionThreadService; import com.google.protobuf.ByteString; import com.google.pubsub.v1.PubsubMessage; import com.google.pubsub.v1.ReceivedMessage; import com.google.pubsub.v1.StreamingPullRequest; import com.google.pubsub.v1.StreamingPullResponse; - import io.grpc.Status; import io.grpc.stub.ServerCallStreamObserver; import io.grpc.stub.StreamObserver; +import java.util.Collections; +import java.util.UUID; +import java.util.concurrent.BlockingQueue; import zipkin2.Span; import zipkin2.codec.SpanBytesEncoder; -public class StreamingPullStreamObserver extends AbstractExecutionThreadService implements StreamObserver { +public class StreamingPullStreamObserver extends AbstractExecutionThreadService + implements StreamObserver { - private final BlockingQueue spanQueue; - private final ServerCallStreamObserver responseObserver; + private final BlockingQueue spanQueue; + private final ServerCallStreamObserver responseObserver; - public StreamingPullStreamObserver(BlockingQueue spanQueue, StreamObserver responseObserver) { - this.spanQueue = spanQueue; - this.responseObserver = (ServerCallStreamObserver) responseObserver; - this.responseObserver.disableAutoInboundFlowControl(); + public StreamingPullStreamObserver(BlockingQueue spanQueue, + StreamObserver responseObserver) { + this.spanQueue = spanQueue; + this.responseObserver = (ServerCallStreamObserver) responseObserver; + this.responseObserver.disableAutoInboundFlowControl(); - this.responseObserver.setOnReadyHandler( - () -> { - if(!isRunning()) { - startAsync().awaitRunning(); - } - this.responseObserver.request(1); - }); - this.responseObserver.setOnCancelHandler(this::stopIfRunning); - - } - - @Override - protected void run() throws Exception { - while (isRunning()) { - if(responseObserver.isReady()) { - Span span = spanQueue.take(); - - StreamingPullResponse.Builder builder = StreamingPullResponse.newBuilder(); - - byte[] encoded = SpanBytesEncoder.JSON_V2.encodeList(Collections.singletonList(span)); - PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(ByteString.copyFrom(encoded)).build(); - ReceivedMessage receivedMessage = ReceivedMessage.newBuilder().setAckId(UUID.randomUUID().toString()).setMessage(pubsubMessage).build(); - - builder.addReceivedMessages(receivedMessage); - - responseObserver.onNext(builder.build()); - } else { - Thread.sleep(1000l); - } - } - } - - @Override - public void onNext(StreamingPullRequest streamingPullRequest) { - if(!isRunning()) { + this.responseObserver.setOnReadyHandler( + () -> { + if (!isRunning()) { startAsync().awaitRunning(); - } - responseObserver.request(1); + } + this.responseObserver.request(1); + }); + this.responseObserver.setOnCancelHandler(this::stopIfRunning); + } + + @Override + protected void run() throws Exception { + while (isRunning()) { + if (responseObserver.isReady()) { + Span span = spanQueue.take(); + + StreamingPullResponse.Builder builder = StreamingPullResponse.newBuilder(); + + byte[] encoded = SpanBytesEncoder.JSON_V2.encodeList(Collections.singletonList(span)); + PubsubMessage pubsubMessage = + PubsubMessage.newBuilder().setData(ByteString.copyFrom(encoded)).build(); + ReceivedMessage receivedMessage = ReceivedMessage.newBuilder() + .setAckId(UUID.randomUUID().toString()) + .setMessage(pubsubMessage) + .build(); + + builder.addReceivedMessages(receivedMessage); + + responseObserver.onNext(builder.build()); + } else { + Thread.sleep(1000l); + } } + } - @Override - public void onError(Throwable throwable) { - if (!Status.fromThrowable(throwable).getCode().equals(Status.CANCELLED.getCode())) { - stopIfRunning(); - } + @Override + public void onNext(StreamingPullRequest streamingPullRequest) { + if (!isRunning()) { + startAsync().awaitRunning(); } + responseObserver.request(1); + } - @Override - public void onCompleted() { - stopIfRunning(); - responseObserver.onCompleted(); + @Override + public void onError(Throwable throwable) { + if (!Status.fromThrowable(throwable).getCode().equals(Status.CANCELLED.getCode())) { + stopIfRunning(); } + } - private void stopIfRunning() { - if (isRunning()) { - stopAsync(); - } - } + @Override + public void onCompleted() { + stopIfRunning(); + responseObserver.onCompleted(); + } + private void stopIfRunning() { + if (isRunning()) { + stopAsync(); + } + } } diff --git a/docker/Dockerfile b/docker/Dockerfile index 9c8c51ce..1dc65521 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -13,14 +13,14 @@ # # zipkin version should match zipkin.version in /pom.xml -ARG zipkin_version=2.24.3 +ARG zipkin_version=2.25.2 # java_version is used during the installation process to build or download the module jar. # # Use latest version here: https://github.com/orgs/openzipkin/packages/container/package/java # This is defined in many places because Docker has no "env" script functionality unless you use # docker-compose: When updating, update everywhere. -ARG java_version=15.0.1_p9 +ARG java_version=21.0.1_p12 # We copy files from the context into a scratch container first to avoid a problem where docker and # docker-compose don't share layer hashes https://github.com/docker/compose/issues/883 normally. diff --git a/module/pom.xml b/module/pom.xml index 8d326115..c5769a3a 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -45,7 +45,19 @@ com.google.auth google-auth-library-oauth2-http - 0.22.0 + ${google-auth-library-oauth2-http.version} + + + commons-codec + commons-codec + + + + + + commons-codec + commons-codec + ${commons-codec.version} io.grpc @@ -160,7 +182,7 @@ io.zipkin.layout zipkin-layout-factory - 1.0.0 + 1.1.0 diff --git a/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageModule.java b/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageModule.java index 6593ea1b..7f5696b1 100644 --- a/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageModule.java +++ b/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -74,8 +74,8 @@ String projectId() { String getDefaultProjectId() { WebClient client = WebClient.of("http://metadata.google.internal/"); return client.execute(RequestHeaders.of( - HttpMethod.GET, "/computeMetadata/v1/project/project-id", - "Metadata-Flavor", "Google")) + HttpMethod.GET, "/computeMetadata/v1/project/project-id", + "Metadata-Flavor", "Google")) .aggregate() .join() .contentUtf8(); diff --git a/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageProperties.java b/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageProperties.java index 325b8c64..61964dc3 100644 --- a/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageProperties.java +++ b/module/src/main/java/zipkin/module/storage/stackdriver/ZipkinStackdriverStorageProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -19,6 +19,7 @@ @ConfigurationProperties("zipkin.storage.stackdriver") public class ZipkinStackdriverStorageProperties implements Serializable { // for Spark jobs private static final long serialVersionUID = 0L; + /** * Sets the level of logging for HTTP requests made by the Stackdriver client. If not set or * none, logging will be disabled. diff --git a/module/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java b/module/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java index a10051f4..59b34bcb 100644 --- a/module/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java +++ b/module/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -76,13 +76,12 @@ public void init() throws IOException { storageProperties = context.getBean(ZipkinStackdriverStorageProperties.class); GoogleCredentials credentials = GoogleCredentials.getApplicationDefault() - .createScoped("https://www.googleapis.com/auth/cloud-platform"); + .createScoped("https://www.googleapis.com/auth/cloud-platform"); channel = ManagedChannelBuilder.forTarget("cloudtrace.googleapis.com") - .build(); + .build(); traceServiceGrpcV1 = TraceServiceGrpc.newBlockingStub(channel) - .withCallCredentials(MoreCallCredentials.from(credentials)); - + .withCallCredentials(MoreCallCredentials.from(credentials)); } @AfterEach @@ -94,47 +93,43 @@ public void close() { } } - @Test - public void healthCheck() { + @Test void healthCheck() { assertThat(storage.check().ok()).isTrue(); } - @Test - public void spanConsumer() throws IOException { + @Test void spanConsumer() throws IOException { Random random = new Random(); Span span = Span.newBuilder() - .traceId(random.nextLong(), random.nextLong()) - .parentId("1") - .id("2") - .name("get") - .kind(Span.Kind.CLIENT) - .localEndpoint(FRONTEND) - .remoteEndpoint(BACKEND) - .timestamp((TODAY + 50L) * 1000L) - .duration(200000L) - .addAnnotation((TODAY + 100L) * 1000L, "foo") - .putTag("http.path", "/api") - .putTag("clnt/finagle.version", "6.45.0") - .build(); - + .traceId(random.nextLong(), random.nextLong()) + .parentId("1") + .id("2") + .name("get") + .kind(Span.Kind.CLIENT) + .localEndpoint(FRONTEND) + .remoteEndpoint(BACKEND) + .timestamp((TODAY + 50L) * 1000L) + .duration(200000L) + .addAnnotation((TODAY + 100L) * 1000L, "foo") + .putTag("http.path", "/api") + .putTag("clnt/finagle.version", "6.45.0") + .build(); storage.spanConsumer().accept(asList(span)).execute(); Trace trace = await() - .atLeast(1, TimeUnit.SECONDS) - .atMost(10, TimeUnit.SECONDS) - .pollInterval(1, TimeUnit.SECONDS) - .ignoreExceptionsMatching(e -> - e instanceof StatusRuntimeException && - ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND - ) - .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() - .setProjectId(projectId) - .setTraceId(span.traceId()) - .build()), t -> t.getSpansCount() == 1); + .atLeast(1, TimeUnit.SECONDS) + .atMost(10, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .ignoreExceptionsMatching(e -> + e instanceof StatusRuntimeException && + ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND + ) + .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() + .setProjectId(projectId) + .setTraceId(span.traceId()) + .build()), t -> t.getSpansCount() == 1); assertThat(trace.getSpans(0).getSpanId()).isEqualTo(2); assertThat(trace.getSpans(0).getParentSpanId()).isEqualTo(1); } - } diff --git a/module/src/test/java/zipkin2/storage/stackdriver/StackdriverMockServer.java b/module/src/test/java/zipkin2/storage/stackdriver/StackdriverMockServer.java index 07b8d86d..5af8cd13 100644 --- a/module/src/test/java/zipkin2/storage/stackdriver/StackdriverMockServer.java +++ b/module/src/test/java/zipkin2/storage/stackdriver/StackdriverMockServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -18,51 +18,28 @@ import com.google.devtools.cloudtrace.v2.Span; import com.google.devtools.cloudtrace.v2.TraceServiceGrpc; import com.google.protobuf.Empty; -import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.grpc.GrpcService; +import com.linecorp.armeria.testing.junit5.server.ServerExtension; import io.grpc.stub.StreamObserver; import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; -import org.junit.rules.ExternalResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static java.util.Collections.unmodifiableSet; /** Starts up a local Stackdriver Trace server, listening for GRPC requests on {@link #grpcURI}. */ -public class StackdriverMockServer extends ExternalResource { - private static final Logger LOG = LoggerFactory.getLogger(StackdriverMockServer.class); - - private final Server server; - +public class StackdriverMockServer extends ServerExtension { private final Set traceIds = Sets.newConcurrentHashSet(); private final Set spanIds = Sets.newConcurrentHashSet(); private CountDownLatch spanCountdown; - public StackdriverMockServer() { - this.server = Server.builder() - .service(GrpcService.builder() - .addService(new Service()) - .build()) - .tlsSelfSigned() - .build(); + @Override protected void configure(ServerBuilder sb) { + sb.service(GrpcService.builder().addService(new Service()).build()).tlsSelfSigned(); } public int getPort() { - return server.activeLocalPort(); - } - - @Override - protected void before() { - this.server.start().join(); - - LOG.info("Started MOCK grpc server on 'localhost:{}'", getPort()); - } - - @Override - public void after() { - this.server.stop().join(); + return server().activeLocalPort(); } public void reset() { @@ -72,8 +49,7 @@ public void reset() { } class Service extends TraceServiceGrpc.TraceServiceImplBase { - @Override - public void batchWriteSpans(BatchWriteSpansRequest request, + @Override public void batchWriteSpans(BatchWriteSpansRequest request, StreamObserver responseObserver) { final List spansList = request.getSpansList(); for (Span span : spansList) { @@ -90,7 +66,7 @@ public void setSpanCountdown(CountDownLatch spanCountdown) { } public String grpcURI() { - return String.format("%s:%s", "localhost", this.getPort()); + return String.format("%s:%s", "localhost", getPort()); } public Set spanIds() { diff --git a/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageIntegrationTest.java b/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageIntegrationTest.java index 1a7b3976..37f6bcc9 100644 --- a/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageIntegrationTest.java +++ b/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -29,10 +29,15 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.LongStream; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -45,36 +50,34 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -public class ZipkinStackdriverStorageIntegrationTest { - @ClassRule public static final StackdriverMockServer mockServer = new StackdriverMockServer(); +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ZipkinStackdriverStorageIntegrationTest { + @Order(0) @RegisterExtension StackdriverMockServer mockServer = new StackdriverMockServer(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); StackdriverStorage storage; ZipkinStackdriverStorageProperties storageProperties; + @Order(1) @RegisterExtension BeforeAllCallback init = new BeforeAllCallback() { + @Override public void beforeAll(ExtensionContext extensionContext) { + TestPropertyValues.of( + "zipkin.storage.type:stackdriver", + "zipkin.storage.stackdriver.project-id:test_project", + "zipkin.storage.stackdriver.api-host:localhost:" + mockServer.getPort()).applyTo(context); + context.register( + PropertyPlaceholderAutoConfiguration.class, + TestConfiguration.class, + ZipkinStackdriverStorageModule.class); + context.refresh(); + storage = context.getBean(StackdriverStorage.class); + storageProperties = context.getBean(ZipkinStackdriverStorageProperties.class); + } + }; - @Before - public void init() { - TestPropertyValues.of( - "zipkin.storage.type:stackdriver", - "zipkin.storage.stackdriver.project-id:test_project", - "zipkin.storage.stackdriver.api-host:localhost:" + mockServer.getPort()).applyTo(context); - context.register( - PropertyPlaceholderAutoConfiguration.class, - TestConfiguration.class, - ZipkinStackdriverStorageModule.class); - context.refresh(); - storage = context.getBean(StackdriverStorage.class); - storageProperties = context.getBean(ZipkinStackdriverStorageProperties.class); - } - - @After - public void close() { + @AfterEach void close() { mockServer.reset(); - context.close(); } - @Test - public void openSSLAvailable() { + @Test void openSSLAvailable() { assertThat(OpenSsl.isAvailable()) .withFailMessage("OpenSsl unavailable:" + OpenSsl.unavailabilityCause()) .isTrue(); @@ -88,8 +91,7 @@ public void openSSLAvailable() { .isEqualTo(SslProvider.OPENSSL); } - @Test - public void mockGrpcServerServesOverSSL() { // sanity checks the mock server + @Test void mockGrpcServerServesOverSSL() { // sanity checks the mock server TraceServiceGrpc.TraceServiceBlockingStub sslTraceService = Clients.builder("gproto+https://" + mockServer.grpcURI() + "/") .factory(ClientFactory.builder() @@ -100,8 +102,7 @@ public void mockGrpcServerServesOverSSL() { // sanity checks the mock server sslTraceService.batchWriteSpans(BatchWriteSpansRequest.getDefaultInstance()); } - @Test - public void traceConsumerGetsCalled() throws Exception { + @Test void traceConsumerGetsCalled() throws Exception { List spanIds = LongStream.of(1, 2, 3) .mapToObj(Long::toHexString) diff --git a/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageModuleTest.java b/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageModuleTest.java index 4a9212f4..93d27907 100644 --- a/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageModuleTest.java +++ b/module/src/test/java/zipkin2/storage/stackdriver/ZipkinStackdriverStorageModuleTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -16,8 +16,8 @@ import com.google.auth.Credentials; import com.google.auth.oauth2.GoogleCredentials; import java.io.IOException; -import org.junit.After; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; @@ -28,32 +28,33 @@ import zipkin.module.storage.stackdriver.ZipkinStackdriverStorageProperties; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; public class ZipkinStackdriverStorageModuleTest { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - @After + @AfterEach public void close() { context.close(); } - @Test(expected = NoSuchBeanDefinitionException.class) - public void doesntProvideStorageComponent_whenStorageTypeNotStackdriver() { - TestPropertyValues.of("zipkin.storage.type:elasticsearch").applyTo(context); - context.register( - PropertyPlaceholderAutoConfiguration.class, - ZipkinStackdriverStorageProperties.class, - ZipkinStackdriverStorageModule.class, - TestConfiguration.class); - context.refresh(); + @Test void doesntProvideStorageComponent_whenStorageTypeNotStackdriver() { + assertThrows(NoSuchBeanDefinitionException.class, () -> { + TestPropertyValues.of("zipkin.storage.type:elasticsearch").applyTo(context); + context.register( + PropertyPlaceholderAutoConfiguration.class, + ZipkinStackdriverStorageProperties.class, + ZipkinStackdriverStorageModule.class, + TestConfiguration.class); + context.refresh(); - context.getBean(StackdriverStorage.class); + context.getBean(StackdriverStorage.class); + }); } - @Test - public void providesStorageComponent_whenStorageTypeStackdriverAndProjectIdSet() { + @Test void providesStorageComponent_whenStorageTypeStackdriverAndProjectIdSet() { TestPropertyValues.of( "zipkin.storage.type:stackdriver", "zipkin.storage.stackdriver.project-id:zipkin", @@ -67,8 +68,7 @@ public void providesStorageComponent_whenStorageTypeStackdriverAndProjectIdSet() assertThat(context.getBean(StackdriverStorage.class)).isNotNull(); } - @Test - public void canOverrideProperty_apiHost() { + @Test void canOverrideProperty_apiHost() { TestPropertyValues.of( "zipkin.storage.type:stackdriver", "zipkin.storage.stackdriver.project-id:zipkin", diff --git a/mvnw b/mvnw index 41c0f0c2..8d937f4c 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven Start Up Batch script +# Apache Maven Wrapper startup batch script, version 3.2.0 # # Required ENV vars: # ------------------ @@ -27,7 +27,6 @@ # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -36,6 +35,10 @@ if [ -z "$MAVEN_SKIP_RC" ] ; then + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi @@ -50,7 +53,7 @@ fi cygwin=false; darwin=false; mingw=false -case "`uname`" in +case "$(uname)" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true @@ -58,9 +61,9 @@ case "`uname`" in # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME else - export JAVA_HOME="/Library/Java/Home" + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi fi ;; @@ -68,68 +71,38 @@ esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + JAVA_HOME=$(java-config --jre-home) fi fi -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi @@ -145,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`which java`" + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi @@ -159,12 +132,9 @@ if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { - if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" @@ -180,96 +150,99 @@ find_maven_basedir() { fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done - echo "${basedir}" + printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" fi } -BASE_DIR=`find_maven_basedir "$(pwd)"` +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi + log "Couldn't find $wrapperJarPath, downloading it ..." + if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi @@ -278,33 +251,58 @@ fi # End of extension ########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 86115719..f80fbad3 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,182 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index db226829..4c47ad35 100644 --- a/pom.xml +++ b/pom.xml @@ -62,59 +62,66 @@ io.zipkin.zipkin2 - 2.24.3 - 2.16.3 - 2.4.1 + 2.25.2 + 2.17.0 + 2.7.18 com.linecorp.armeria - 1.3.0 + 1.26.4 io.zipkin.brave - 5.13.7 + 5.16.0 - 1.33.1 + 1.58.0 - 3.12.0 - 29.0-android + 3.24.0 + 32.0.1-android + + 1.20.0 + + 1.16.0 - 1.2.10 + 2.32.0 - 3.18.1 - 4.0.3 - 4.13.1 - 5.7.0 - 3.6.28 + + 1.125.13 + 1.107.13 + + 3.24.2 + 4.2.0 + 5.10.1 + 5.8.0 - 2.4.0 + 2.23.0 ${skipTests} - 1.19 + 1.23 1.2.8 - 4.2 - 3.8.1 + 4.3 + 3.11.0 - 3.1.2 - 3.0.0-M1 - 3.0.0-M3 + 3.6.1 + 3.1.1 + 3.4.1 - 3.2.0 - 3.0.0-M1 - 3.2.0 - 3.2.0 - 3.0.0-M1 - 3.2.4 - 3.2.1 - 3.0.0-M5 - 1.6.8 + 3.4.0 + 3.1.1 + 3.6.2 + 3.3.0 + 3.0.1 + 3.5.1 + 3.3.0 + 3.2.2 + 1.6.13 Zipkin Google Cloud Platform (Parent) @@ -151,63 +158,28 @@ + + + + com.asarkar.grpc + grpc-test + 1.2.2 + + + org.junit.jupiter + * + + + + + - - io.zipkin.zipkin2 - zipkin-collector - ${zipkin.version} - - - io.zipkin.reporter2 - zipkin-reporter - ${zipkin-reporter.version} - - - - ${zipkin.groupId} - zipkin-tests - ${zipkin.version} - test - - - - junit - junit - ${junit.version} - test - - org.junit.jupiter junit-jupiter ${junit-jupiter.version} test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - org.assertj assertj-core @@ -218,12 +190,12 @@ ch.qos.logback logback-classic - 1.2.3 + 1.2.13 test org.mockito - mockito-core + mockito-junit-jupiter ${mockito.version} test @@ -232,16 +204,6 @@ - - - io.takari - maven - 0.7.7 - - 3.6.3 - - - de.qaware.maven @@ -347,32 +309,56 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - + false + + -Dnet.bytebuddy.experimental=true + + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + + maven-failsafe-plugin ${maven-surefire-plugin.version} - - - false - - false - - false - integration-test - verify integration-test + + + + verify + verify + + + + always + + + false + + false + + -Dnet.bytebuddy.experimental=true + @@ -410,7 +396,9 @@ - [11,16) + + [11,12),[17,18),[21,22) @@ -521,15 +509,25 @@ + - error-prone + error-prone-11+ - true + + [11,12),[17,18),[21,22) maven-compiler-plugin + ${maven-compiler-plugin.version} + true + + ${main.java.version} + ${main.java.version} + true + true + @@ -543,6 +541,17 @@ -XDcompilePolicy=simple -Xplugin:ErrorProne ${errorprone.args} + + -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED @@ -570,9 +579,10 @@ ossrh https://oss.sonatype.org/ - - 10 + + 20 + 30 true @@ -580,7 +590,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.1.0 sign-artifacts diff --git a/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/StackdriverTracePropagationTest.java b/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/StackdriverTracePropagationTest.java index 08e4829c..15119f91 100644 --- a/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/StackdriverTracePropagationTest.java +++ b/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/StackdriverTracePropagationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -19,7 +19,7 @@ import brave.propagation.TraceContextOrSamplingFlags; import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -35,8 +35,7 @@ public class StackdriverTracePropagationTest { StackdriverTracePropagation.newFactory(B3Propagation.FACTORY).get(); TraceContext.Extractor> extractor = propagation.extractor(Map::get); - @Test - public void b3TakesPrecedenceOverXCloud() { + @Test void b3TakesPrecedenceOverXCloud() { Map headers = new HashMap<>(); headers.put(StackdriverTracePropagation.TRACE_ID_NAME, XCLOUD_VALUE); @@ -47,8 +46,7 @@ public void b3TakesPrecedenceOverXCloud() { assertThat(ctx.context().traceIdString()).isEqualTo(B3_TRACE_ID); } - @Test - public void xCloudReturnedWhenB3Missing() { + @Test void xCloudReturnedWhenB3Missing() { Map headers = new HashMap<>(); headers.put(StackdriverTracePropagation.TRACE_ID_NAME, XCLOUD_VALUE); @@ -57,8 +55,7 @@ public void xCloudReturnedWhenB3Missing() { assertThat(ctx.context().traceIdString()).isEqualTo(XCLOUD_TRACE_ID); } - @Test - public void b3ReturnedWhenXCloudMissing() { + @Test void b3ReturnedWhenXCloudMissing() { Map headers = new HashMap<>(); headers.put(B3_HEADER, B3_VALUE); @@ -67,8 +64,7 @@ public void b3ReturnedWhenXCloudMissing() { assertThat(ctx.context().traceIdString()).isEqualTo(B3_TRACE_ID); } - @Test - public void emptyContextReturnedWhenNoHeadersPresent() { + @Test void emptyContextReturnedWhenNoHeadersPresent() { TraceContextOrSamplingFlags ctx = extractor.extract(new HashMap<>()); assertThat(ctx).isSameAs(TraceContextOrSamplingFlags.EMPTY); diff --git a/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/XCloudTraceContextExtractorTest.java b/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/XCloudTraceContextExtractorTest.java index b54d3410..e820a245 100644 --- a/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/XCloudTraceContextExtractorTest.java +++ b/propagation-stackdriver/src/test/java/brave/propagation/stackdriver/XCloudTraceContextExtractorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -16,15 +16,14 @@ import brave.propagation.B3Propagation; import brave.propagation.Propagation; import brave.propagation.TraceContextOrSamplingFlags; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; public class XCloudTraceContextExtractorTest { - @Test - public void testExtractXCloudTraceContext_traceTrue() { + @Test void testExtractXCloudTraceContext_traceTrue() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/4981115762139876185;o=1"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -38,8 +37,7 @@ public void testExtractXCloudTraceContext_traceTrue() { assertThat(context.context().sampled()).isTrue(); } - @Test - public void testExtractXCloudTraceContext_spanIdZero() { + @Test void testExtractXCloudTraceContext_spanIdZero() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/0;o=1"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -52,8 +50,7 @@ public void testExtractXCloudTraceContext_spanIdZero() { assertThat(context.traceIdContext().sampled()).isTrue(); } - @Test - public void testExtractXCloudTraceContext_traceFalse() { + @Test void testExtractXCloudTraceContext_traceFalse() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/4981115762139876185;o=0"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -64,8 +61,7 @@ public void testExtractXCloudTraceContext_traceFalse() { assertThat(context.context().sampled()).isFalse(); } - @Test - public void testExtractXCloudTraceContext_missingTraceTrueValue() { + @Test void testExtractXCloudTraceContext_missingTraceTrueValue() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/4981115762139876185;o="; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -79,8 +75,7 @@ public void testExtractXCloudTraceContext_missingTraceTrueValue() { assertThat(context.context().sampled()).isNull(); } - @Test - public void testExtractXCloudTraceContext_noTraceTrue() { + @Test void testExtractXCloudTraceContext_noTraceTrue() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/4981115762139876185"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -94,8 +89,7 @@ public void testExtractXCloudTraceContext_noTraceTrue() { assertThat(context.context().sampled()).isNull(); } - @Test - public void testExtractXCloudTraceContext_noSpanId() { + @Test void testExtractXCloudTraceContext_noSpanId() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( @@ -108,8 +102,7 @@ public void testExtractXCloudTraceContext_noSpanId() { assertThat(context.traceIdContext().sampled()).isNull(); } - @Test - public void testExtractXCloudTraceContext_unsignedLong() { + @Test void testExtractXCloudTraceContext_unsignedLong() { String xCloudTraceContext = "8fd836bcfe241ee19a057679a77ba317/13804021222261907717"; XCloudTraceContextExtractor extractor = new XCloudTraceContextExtractor<>( B3Propagation.FACTORY.get(), (request, key) -> xCloudTraceContext); @@ -121,8 +114,7 @@ public void testExtractXCloudTraceContext_unsignedLong() { assertThat(context.context().sampled()).isNull(); } - @Test - public void parseUnsignedLong() { + @Test void parseUnsignedLong() { // max int64 assertThat(XCloudTraceContextExtractor.parseUnsignedLong("9223372036854775807")) .isEqualTo(Long.parseUnsignedLong("9223372036854775807")); diff --git a/sender-pubsub/pom.xml b/sender-pubsub/pom.xml index 1da90e87..e2ef88b6 100644 --- a/sender-pubsub/pom.xml +++ b/sender-pubsub/pom.xml @@ -1,7 +1,7 @@ com.google.api.grpc @@ -64,27 +70,39 @@ test - io.grpc - grpc-testing - ${grpc.version} + com.asarkar.grpc + grpc-test test io.grpc - grpc-auth + grpc-inprocess ${grpc.version} test io.grpc - grpc-netty-shaded + grpc-auth ${grpc.version} test com.google.auth google-auth-library-oauth2-http - 0.22.2 + ${google-auth-library-oauth2-http.version} + + + commons-codec + commons-codec + + + test + + + + commons-codec + commons-codec + ${commons-codec.version} test diff --git a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/StackdriverSender.java b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/StackdriverSender.java index eddff6ce..e91930bf 100644 --- a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/StackdriverSender.java +++ b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/StackdriverSender.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -34,9 +34,9 @@ import zipkin2.reporter.Sender; import zipkin2.reporter.stackdriver.internal.UnaryClientCall; -import static zipkin2.reporter.stackdriver.internal.UnaryClientCall.DEFAULT_SERVER_TIMEOUT_MS; import static com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag; import static io.grpc.CallOptions.DEFAULT; +import static zipkin2.reporter.stackdriver.internal.UnaryClientCall.DEFAULT_SERVER_TIMEOUT_MS; public final class StackdriverSender extends Sender { @@ -76,7 +76,9 @@ public Builder callOptions(CallOptions callOptions) { } public Builder serverResponseTimeoutMs(long serverResponseTimeoutMs) { - if (serverResponseTimeoutMs <= 0) throw new IllegalArgumentException("Server response timeout must be greater than 0"); + if (serverResponseTimeoutMs <= 0) { + throw new IllegalArgumentException("Server response timeout must be greater than 0"); + } this.serverResponseTimeoutMs = serverResponseTimeoutMs; return this; } @@ -173,6 +175,7 @@ public Call sendSpans(List traceIdPrefixedSpans) { /** * Sends a malformed call to Stackdriver Trace to validate service health. + * * @return successful status if Stackdriver Trace API responds with expected validation * error (or happens to respond as success -- unexpected but okay); otherwise returns error status * wrapping the underlying exception. @@ -246,7 +249,8 @@ int spanFieldSize(int traceIdPrefixedSpanSize) { final class BatchWriteSpansCall extends UnaryClientCall { BatchWriteSpansCall(BatchWriteSpansRequest request) { - super(channel, TraceServiceGrpc.getBatchWriteSpansMethod(), callOptions, request, serverResponseTimeoutMs); + super(channel, TraceServiceGrpc.getBatchWriteSpansMethod(), callOptions, request, + serverResponseTimeoutMs); } @Override diff --git a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/AwaitableUnaryClientCallListener.java b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/AwaitableUnaryClientCallListener.java index 1b6cb2b9..0ff93dbf 100644 --- a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/AwaitableUnaryClientCallListener.java +++ b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/AwaitableUnaryClientCallListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -32,7 +32,9 @@ final class AwaitableUnaryClientCallListener extends ClientCall.Listener { long serverTimeoutMs; // how long to wait for server response in milliseconds AwaitableUnaryClientCallListener(long serverTimeoutMs) { - if (serverTimeoutMs <= 0) throw new IllegalArgumentException("Server response timeout must be greater than 0"); + if (serverTimeoutMs <= 0) { + throw new IllegalArgumentException("Server response timeout must be greater than 0"); + } this.serverTimeoutMs = serverTimeoutMs; } @@ -46,8 +48,9 @@ V await() throws IOException { while (true) { try { if (!countDown.await(serverTimeoutMs, TimeUnit.MILLISECONDS)) { - throw new IllegalStateException("timeout waiting for onClose. timeoutMs=" + serverTimeoutMs - + ", resultSet=" + resultSet); + throw new IllegalStateException( + "timeout waiting for onClose. timeoutMs=" + serverTimeoutMs + + ", resultSet=" + resultSet); } Object result; synchronized (this) { @@ -74,7 +77,8 @@ V await() throws IOException { } @Override - public void onHeaders(Metadata headers) {} + public void onHeaders(Metadata headers) { + } @Override public synchronized void onMessage(V value) { diff --git a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/CallbackToUnaryClientCallListener.java b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/CallbackToUnaryClientCallListener.java index 1492ed19..a8c65c88 100644 --- a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/CallbackToUnaryClientCallListener.java +++ b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/CallbackToUnaryClientCallListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -30,7 +30,8 @@ final class CallbackToUnaryClientCallListener extends ClientCall.Listener } @Override - public void onHeaders(Metadata headers) {} + public void onHeaders(Metadata headers) { + } @Override public synchronized void onMessage(RespT value) { diff --git a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/UnaryClientCall.java b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/UnaryClientCall.java index 59666fd9..2688c86c 100644 --- a/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/UnaryClientCall.java +++ b/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/internal/UnaryClientCall.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -29,11 +29,11 @@ public abstract class UnaryClientCall extends Call.Base { final long serverTimeoutMs; protected UnaryClientCall( - Channel channel, - MethodDescriptor descriptor, - CallOptions callOptions, - ReqT request, - long serverTimeoutMs) { + Channel channel, + MethodDescriptor descriptor, + CallOptions callOptions, + ReqT request, + long serverTimeoutMs) { this.call = channel.newCall(descriptor, callOptions); this.request = request; this.serverTimeoutMs = serverTimeoutMs; @@ -45,7 +45,8 @@ protected final ReqT request() { @Override protected final RespT doExecute() throws IOException { - AwaitableUnaryClientCallListener listener = new AwaitableUnaryClientCallListener<>(this.serverTimeoutMs); + AwaitableUnaryClientCallListener listener = + new AwaitableUnaryClientCallListener<>(this.serverTimeoutMs); beginUnaryCall(listener); return listener.await(); } diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/AsyncReporterStackdriverSenderTest.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/AsyncReporterStackdriverSenderTest.java index c51f2c2d..030687db 100644 --- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/AsyncReporterStackdriverSenderTest.java +++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/AsyncReporterStackdriverSenderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,16 +13,22 @@ */ package zipkin2.reporter.stackdriver; +import com.asarkar.grpc.test.GrpcCleanupExtension; +import com.asarkar.grpc.test.Resources; import com.google.devtools.cloudtrace.v2.BatchWriteSpansRequest; import com.google.devtools.cloudtrace.v2.TraceServiceGrpc; import com.google.protobuf.Empty; +import io.grpc.ManagedChannel; +import io.grpc.Server; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.stub.StreamObserver; -import io.grpc.testing.GrpcServerRule; +import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; import zipkin2.Span; @@ -39,31 +45,38 @@ import static org.mockito.Mockito.verify; /** Same as StackdriverSpanConsumerTest: tests everything wired together */ -public class AsyncReporterStackdriverSenderTest { - @Rule public final GrpcServerRule server = new GrpcServerRule().directExecutor(); +@ExtendWith(GrpcCleanupExtension.class) +class AsyncReporterStackdriverSenderTest { TestTraceService traceService = spy(new TestTraceService()); String projectId = "test-project"; AsyncReporter reporter; - @Before - public void setUp() { - server.getServiceRegistry().addService(traceService); - reporter = - AsyncReporter.builder( - StackdriverSender.newBuilder(server.getChannel()).projectId(projectId).build()) - .messageTimeout(0, TimeUnit.MILLISECONDS) // don't spawn a thread - .build(StackdriverEncoder.V2); + @BeforeEach void setUp(Resources resources) throws Exception { + String serverName = InProcessServerBuilder.generateName(); + + Server server = InProcessServerBuilder + .forName(serverName) + .directExecutor() + .addService(traceService) + .build().start(); + resources.register(server, Duration.ofSeconds(10)); // shutdown deadline + + ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + resources.register(channel, Duration.ofSeconds(10));// close deadline + + reporter = AsyncReporter.builder( + StackdriverSender.newBuilder(channel).projectId(projectId).build()) + .messageTimeout(0, TimeUnit.MILLISECONDS) // don't spawn a thread + .build(StackdriverEncoder.V2); } - @Test - public void sendSpans_empty() { + @Test void sendSpans_empty() { reporter.flush(); verify(traceService, never()).batchWriteSpans(any(), any()); } - @Test - public void sendSpans() { + @Test void sendSpans() { onClientCall( observer -> { observer.onNext(Empty.getDefaultInstance()); @@ -87,16 +100,17 @@ public void sendSpans() { void onClientCall(Consumer> onClientCall) { doAnswer( - (Answer) - invocationOnMock -> { - StreamObserver observer = - ((StreamObserver) invocationOnMock.getArguments()[1]); - onClientCall.accept(observer); - return null; - }) + (Answer) + invocationOnMock -> { + StreamObserver observer = + ((StreamObserver) invocationOnMock.getArguments()[1]); + onClientCall.accept(observer); + return null; + }) .when(traceService) .batchWriteSpans(any(BatchWriteSpansRequest.class), any(StreamObserver.class)); } - static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase {} + static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase { + } } diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java index 92596509..6ed6e1ce 100644 --- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java +++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -62,13 +62,13 @@ public void setUp() throws IOException { assumeThatCode(GoogleCredentials::getApplicationDefault).doesNotThrowAnyException(); credentials = GoogleCredentials.getApplicationDefault() - .createScoped(Collections.singletonList("https://www.googleapis.com/auth/trace.append")); + .createScoped(Collections.singletonList("https://www.googleapis.com/auth/trace.append")); // Setup the sender to authenticate the Google Stackdriver service sender = StackdriverSender.newBuilder() - .projectId(projectId) - .callOptions(CallOptions.DEFAULT.withCallCredentials(MoreCallCredentials.from(credentials))) - .build(); + .projectId(projectId) + .callOptions(CallOptions.DEFAULT.withCallCredentials(MoreCallCredentials.from(credentials))) + .build(); reporter = AsyncReporter.builder(sender) @@ -76,16 +76,17 @@ public void setUp() throws IOException { .build(StackdriverEncoder.V2); traceServiceGrpcV1 = TraceServiceGrpc.newBlockingStub(sender.channel) - .withCallCredentials(MoreCallCredentials.from(credentials.createScoped("https://www.googleapis.com/auth/cloud-platform"))); + .withCallCredentials(MoreCallCredentials.from( + credentials.createScoped("https://www.googleapis.com/auth/cloud-platform"))); senderNoPermission = StackdriverSender.newBuilder() - .projectId(projectId) - .build(); + .projectId(projectId) + .build(); reporterNoPermission = - AsyncReporter.builder(senderNoPermission) - .messageTimeout(0, TimeUnit.MILLISECONDS) - .build(StackdriverEncoder.V2); + AsyncReporter.builder(senderNoPermission) + .messageTimeout(0, TimeUnit.MILLISECONDS) + .build(StackdriverEncoder.V2); } @AfterEach @@ -98,81 +99,78 @@ public void tearDown() { } } - @Test - public void healthcheck() { + @Test void healthcheck() { assertThat(reporter.check().ok()).isTrue(); } - @Test - public void sendSpans() { + @Test void sendSpans() { Random random = new Random(); Span span = Span.newBuilder() - .traceId(random.nextLong(), random.nextLong()) - .parentId("1") - .id("2") - .name("get") - .kind(Span.Kind.CLIENT) - .localEndpoint(FRONTEND) - .remoteEndpoint(BACKEND) - .timestamp((TODAY + 50L) * 1000L) - .duration(200000L) - .addAnnotation((TODAY + 100L) * 1000L, "foo") - .putTag("http.path", "/api") - .putTag("clnt/finagle.version", "6.45.0") - .build(); + .traceId(random.nextLong(), random.nextLong()) + .parentId("1") + .id("2") + .name("get") + .kind(Span.Kind.CLIENT) + .localEndpoint(FRONTEND) + .remoteEndpoint(BACKEND) + .timestamp((TODAY + 50L) * 1000L) + .duration(200000L) + .addAnnotation((TODAY + 100L) * 1000L, "foo") + .putTag("http.path", "/api") + .putTag("clnt/finagle.version", "6.45.0") + .build(); reporter.report(span); reporter.flush(); Trace trace = await() - .atLeast(1, TimeUnit.SECONDS) - .atMost(10, TimeUnit.SECONDS) - .pollInterval(1, TimeUnit.SECONDS) - .ignoreExceptionsMatching(e -> - e instanceof StatusRuntimeException && - ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND - ) - .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() - .setProjectId(projectId) - .setTraceId(span.traceId()) - .build()), t -> t.getSpansCount() == 1); + .atLeast(1, TimeUnit.SECONDS) + .atMost(10, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .ignoreExceptionsMatching(e -> + e instanceof StatusRuntimeException && + ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND + ) + .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() + .setProjectId(projectId) + .setTraceId(span.traceId()) + .build()), t -> t.getSpansCount() == 1); assertThat(trace.getSpans(0).getSpanId()).isEqualTo(2); assertThat(trace.getSpans(0).getParentSpanId()).isEqualTo(1); } - @Test - public void sendSpanEmptyName() { + @Test void sendSpanEmptyName() { Random random = new Random(); Span span = Span.newBuilder() - .traceId(random.nextLong(), random.nextLong()) - .parentId("1") - .id("2") - .kind(Span.Kind.CLIENT) - .localEndpoint(FRONTEND) - .remoteEndpoint(BACKEND) - .timestamp((TODAY + 50L) * 1000L) - .duration(200000L) - .addAnnotation((TODAY + 100L) * 1000L, "foo") - .putTag("http.path", "/api") - .putTag("clnt/finagle.version", "6.45.0") - .build(); + .traceId(random.nextLong(), random.nextLong()) + .parentId("1") + .id("2") + .kind(Span.Kind.CLIENT) + .localEndpoint(FRONTEND) + .remoteEndpoint(BACKEND) + .timestamp((TODAY + 50L) * 1000L) + .duration(200000L) + .addAnnotation((TODAY + 100L) * 1000L, "foo") + .putTag("http.path", "/api") + .putTag("clnt/finagle.version", "6.45.0") + .build(); reporter.report(span); reporter.flush(); Trace trace = await() - .atLeast(1, TimeUnit.SECONDS) - .atMost(10, TimeUnit.SECONDS) - .pollInterval(1, TimeUnit.SECONDS) - .ignoreExceptionsMatching(e -> - e instanceof StatusRuntimeException && - ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND - ) - .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() - .setProjectId(projectId) - .setTraceId(span.traceId()) - .build()), t -> t.getSpansCount() == 1); + .atLeast(1, TimeUnit.SECONDS) + .atMost(10, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .ignoreExceptionsMatching(e -> + e instanceof StatusRuntimeException && + ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND + ) + .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder() + .setProjectId(projectId) + .setTraceId(span.traceId()) + .build()), t -> t.getSpansCount() == 1); // In Stackdriver Trace v2 API, Zipkin Span "name" is sent as Stackdriver Span "displayName" // However, in Stackdriver Trace v1 API, to read this back, it's Stackdriver TraceSpan's "name" @@ -181,12 +179,11 @@ public void sendSpanEmptyName() { assertThat(trace.getSpans(0).getParentSpanId()).isEqualTo(1); } - @Test - public void healthcheckFailNoPermission() { + @Test void healthcheckFailNoPermission() { CheckResult result = reporterNoPermission.check(); assertThat(result.ok()).isFalse(); assertThat(result.error()).isNotNull(); assertThat(result.error()).isInstanceOfSatisfying(StatusRuntimeException.class, - sre -> assertThat(sre.getStatus().getCode()).isEqualTo(Status.Code.PERMISSION_DENIED)); + sre -> assertThat(sre.getStatus().getCode()).isEqualTo(Status.Code.PERMISSION_DENIED)); } } diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverEncoderTest.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverEncoderTest.java index 2ffe3bf7..95a82aa3 100644 --- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverEncoderTest.java +++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverEncoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package zipkin2.reporter.stackdriver; -import org.junit.Test; +import org.junit.jupiter.api.Test; import zipkin2.Span; import zipkin2.TestObjects; import zipkin2.translation.stackdriver.SpanTranslator; @@ -24,26 +24,22 @@ public class StackdriverEncoderTest { StackdriverEncoder encoder = StackdriverEncoder.V2; Span zipkinSpan = TestObjects.CLIENT_SPAN; - @Test - public void sizeInBytes() { + @Test void sizeInBytes() { assertThat(encoder.sizeInBytes(zipkinSpan)).isEqualTo(encoder.encode(zipkinSpan).length); } - @Test - public void sizeInBytes_64BitTraceId() { + @Test void sizeInBytes_64BitTraceId() { String traceId = "216a2aea45d08fc9"; zipkinSpan = zipkinSpan.toBuilder().traceId(traceId).build(); assertThat(encoder.sizeInBytes(zipkinSpan)).isEqualTo(encoder.encode(zipkinSpan).length); } - @Test - public void encode_writesTraceIdPrefixedSpan() throws Exception { + @Test void encode_writesTraceIdPrefixedSpan() throws Exception { assertTraceIdPrefixedSpan(encoder.encode(zipkinSpan), zipkinSpan.traceId()); } - @Test - public void encode_writesPaddedTraceIdPrefixedSpan() throws Exception { + @Test void encode_writesPaddedTraceIdPrefixedSpan() throws Exception { String traceId = "216a2aea45d08fc9"; zipkinSpan = zipkinSpan.toBuilder().traceId(traceId).build(); diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverSenderTest.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverSenderTest.java index 586e7c68..7eb59894 100644 --- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverSenderTest.java +++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/StackdriverSenderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,21 +13,27 @@ */ package zipkin2.reporter.stackdriver; +import com.asarkar.grpc.test.GrpcCleanupExtension; +import com.asarkar.grpc.test.Resources; import com.google.common.collect.ImmutableList; import com.google.devtools.cloudtrace.v2.BatchWriteSpansRequest; import com.google.devtools.cloudtrace.v2.TraceServiceGrpc; import com.google.protobuf.Empty; +import io.grpc.ManagedChannel; +import io.grpc.Server; import io.grpc.Status; import io.grpc.StatusRuntimeException; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.stub.StreamObserver; -import io.grpc.testing.GrpcServerRule; import java.io.IOException; +import java.time.Duration; import java.util.List; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; import zipkin2.CheckResult; @@ -41,22 +47,31 @@ import static org.mockito.Mockito.verify; import static zipkin2.TestObjects.FRONTEND; -public class StackdriverSenderTest { - @Rule public final GrpcServerRule server = new GrpcServerRule().directExecutor(); +@ExtendWith(GrpcCleanupExtension.class) +class StackdriverSenderTest { TestTraceService traceService = spy(new TestTraceService()); String projectId = "test-project"; StackdriverSender sender; Span span = Span.newBuilder().traceId("1").id("a").name("get").localEndpoint(FRONTEND).build(); - @Before - public void setUp() { - server.getServiceRegistry().addService(traceService); - sender = StackdriverSender.newBuilder(server.getChannel()).projectId(projectId).build(); + @BeforeEach void setUp(Resources resources) throws Exception { + String serverName = InProcessServerBuilder.generateName(); + + Server server = InProcessServerBuilder + .forName(serverName) + .directExecutor() + .addService(traceService) + .build().start(); + resources.register(server, Duration.ofSeconds(10)); // shutdown deadline + + ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + resources.register(channel, Duration.ofSeconds(10));// close deadline + + sender = StackdriverSender.newBuilder(channel).projectId(projectId).build(); } - @Test - public void verifyRequestSent_single() throws IOException { + @Test void verifyRequestSent_single() throws IOException { byte[] oneTrace = StackdriverEncoder.V2.encode(span); List encodedSpans = ImmutableList.of(oneTrace); @@ -73,8 +88,7 @@ public void verifyRequestSent_single() throws IOException { assertThat(sender.messageSizeInBytes(oneTrace.length)).isEqualTo(actualSize); } - @Test - public void verifyRequestSent_multipleTraces() throws IOException { + @Test void verifyRequestSent_multipleTraces() throws IOException { // intentionally change only the boundaries to help break any offset-based logic List spans = ImmutableList.of( @@ -86,8 +100,7 @@ public void verifyRequestSent_multipleTraces() throws IOException { verifyRequestSent(spans); } - @Test - public void verifyRequestSent_multipleSpans() throws IOException { + @Test void verifyRequestSent_multipleSpans() throws IOException { // intentionally change only the boundaries to help break any offset-based logic List spans = ImmutableList.of( @@ -125,8 +138,7 @@ void verifyRequestSent(List spans) throws IOException { assertThat(sender.messageSizeInBytes(encodedSpans)).isEqualTo(actualSize); } - @Test - public void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { + @Test void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { onClientCall(observer -> { observer.onError(new StatusRuntimeException(Status.RESOURCE_EXHAUSTED)); }); @@ -137,8 +149,7 @@ public void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { .hasMessageContaining("RESOURCE_EXHAUSTED"); } - @Test - public void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { + @Test void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { onClientCall(observer -> { observer.onError(new RuntimeException("oh no")); }); @@ -149,16 +160,14 @@ public void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { .hasMessageContaining("UNKNOWN"); } - @Test - public void verifyCheckReturnsOkWhenExpectedValidationFailure() { + @Test void verifyCheckReturnsOkWhenExpectedValidationFailure() { onClientCall(observer -> { observer.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT)); }); assertThat(sender.check()).isSameAs(CheckResult.OK); } - @Test - public void verifyCheckReturnsOkWhenServiceSucceeds() { + @Test void verifyCheckReturnsOkWhenServiceSucceeds() { onClientCall(observer -> { observer.onNext(Empty.getDefaultInstance()); observer.onCompleted(); @@ -168,13 +177,13 @@ public void verifyCheckReturnsOkWhenServiceSucceeds() { void onClientCall(Consumer> onClientCall) { doAnswer( - (Answer) - invocationOnMock -> { - StreamObserver observer = - ((StreamObserver) invocationOnMock.getArguments()[1]); - onClientCall.accept(observer); - return null; - }) + (Answer) + invocationOnMock -> { + StreamObserver observer = + ((StreamObserver) invocationOnMock.getArguments()[1]); + onClientCall.accept(observer); + return null; + }) .when(traceService) .batchWriteSpans(any(BatchWriteSpansRequest.class), any(StreamObserver.class)); } @@ -188,5 +197,6 @@ BatchWriteSpansRequest takeRequest() { return requestCaptor.getValue(); } - static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase {} + static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase { + } } diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/internal/UnaryClientCallTest.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/internal/UnaryClientCallTest.java index 7a413c2a..3e17fa4d 100644 --- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/internal/UnaryClientCallTest.java +++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/internal/UnaryClientCallTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,42 +13,51 @@ */ package zipkin2.reporter.stackdriver.internal; +import com.asarkar.grpc.test.GrpcCleanupExtension; +import com.asarkar.grpc.test.Resources; import com.google.devtools.cloudtrace.v2.BatchWriteSpansRequest; import com.google.devtools.cloudtrace.v2.TraceServiceGrpc; import com.google.protobuf.Empty; import io.grpc.Channel; +import io.grpc.ManagedChannel; +import io.grpc.Server; import io.grpc.StatusRuntimeException; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.stub.StreamObserver; -import io.grpc.testing.GrpcServerRule; +import java.time.Duration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; import zipkin2.Callback; import static io.grpc.CallOptions.DEFAULT; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static zipkin2.reporter.stackdriver.internal.UnaryClientCall.DEFAULT_SERVER_TIMEOUT_MS; -public class UnaryClientCallTest { - @Rule public final GrpcServerRule server = new GrpcServerRule().directExecutor(); +@ExtendWith(GrpcCleanupExtension.class) +class UnaryClientCallTest { final TestTraceService traceService = spy(new TestTraceService()); static class BatchWriteSpansCall extends UnaryClientCall { final Channel channel; - BatchWriteSpansCall(Channel channel, BatchWriteSpansRequest request, long serverResponseTimeout) { - super(channel, TraceServiceGrpc.getBatchWriteSpansMethod(), DEFAULT, request, serverResponseTimeout); + BatchWriteSpansCall(Channel channel, BatchWriteSpansRequest request, + long serverResponseTimeout) { + super(channel, TraceServiceGrpc.getBatchWriteSpansMethod(), DEFAULT, request, + serverResponseTimeout); this.channel = channel; } @@ -60,32 +69,41 @@ public BatchWriteSpansCall clone() { BatchWriteSpansCall call; - @Before - public void setUp() { - server.getServiceRegistry().addService(traceService); - call = new BatchWriteSpansCall(server.getChannel(), BatchWriteSpansRequest.newBuilder().build(), DEFAULT_SERVER_TIMEOUT_MS); + @BeforeEach void setUp(Resources resources) throws Exception { + String serverName = InProcessServerBuilder.generateName(); + + Server server = InProcessServerBuilder + .forName(serverName) + .directExecutor() + .addService(traceService) + .build().start(); + resources.register(server, Duration.ofSeconds(10)); // shutdown deadline + + ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + resources.register(channel, Duration.ofSeconds(10));// close deadline + + call = new BatchWriteSpansCall(channel, BatchWriteSpansRequest.newBuilder().build(), + DEFAULT_SERVER_TIMEOUT_MS); } - @Test - public void execute_success() throws Throwable { + @Test void execute_success() throws Throwable { onClientCall( - observer -> { - observer.onNext(Empty.getDefaultInstance()); - observer.onCompleted(); - }); + observer -> { + observer.onNext(Empty.getDefaultInstance()); + observer.onCompleted(); + }); call.execute(); verifyPatchRequestSent(); } - @Test - public void enqueue_success() throws Throwable { + @Test void enqueue_success() throws Throwable { onClientCall( - observer -> { - observer.onNext(Empty.getDefaultInstance()); - observer.onCompleted(); - }); + observer -> { + observer.onNext(Empty.getDefaultInstance()); + observer.onCompleted(); + }); awaitCallbackResult(); @@ -94,7 +112,7 @@ public void enqueue_success() throws Throwable { void verifyPatchRequestSent() { ArgumentCaptor requestCaptor = - ArgumentCaptor.forClass(BatchWriteSpansRequest.class); + ArgumentCaptor.forClass(BatchWriteSpansRequest.class); verify(traceService).batchWriteSpans(requestCaptor.capture(), any()); @@ -102,69 +120,75 @@ void verifyPatchRequestSent() { assertThat(request).isEqualTo(BatchWriteSpansRequest.getDefaultInstance()); } - @Test(expected = StatusRuntimeException.class) - public void accept_execute_serverError() throws Throwable { - onClientCall(observer -> observer.onError(new IllegalStateException())); + @Test void accept_execute_serverError() throws Throwable { + assertThrows(StatusRuntimeException.class, () -> { + onClientCall(observer -> observer.onError(new IllegalStateException())); - call.execute(); + call.execute(); + }); } - @Test(expected = StatusRuntimeException.class) - public void accept_enqueue_serverError() throws Throwable { - onClientCall(observer -> observer.onError(new IllegalStateException())); + @Test void accept_enqueue_serverError() throws Throwable { + assertThrows(StatusRuntimeException.class, () -> { + onClientCall(observer -> observer.onError(new IllegalStateException())); - awaitCallbackResult(); + awaitCallbackResult(); + }); } - @Test(expected = IllegalStateException.class) - public void execute_timeout() throws Throwable { - long overriddenTimeout = 50; - call = new BatchWriteSpansCall(server.getChannel(), BatchWriteSpansRequest.newBuilder().build(), overriddenTimeout); - onClientCall( - observer -> - Executors.newSingleThreadExecutor().submit(() -> - { - try { - Thread.sleep(overriddenTimeout + 10); - } catch (InterruptedException e) {} - observer.onCompleted(); - })); - - call.execute(); + @Test void execute_timeout() throws Throwable { + assertThrows(IllegalStateException.class, () -> { + long overriddenTimeout = 50; + call = new BatchWriteSpansCall(call.channel, BatchWriteSpansRequest.newBuilder().build(), + overriddenTimeout); + onClientCall( + observer -> + Executors.newSingleThreadExecutor().submit(() -> + { + try { + Thread.sleep(overriddenTimeout + 10); + } catch (InterruptedException e) { + } + observer.onCompleted(); + })); + + call.execute(); + }); } - static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase {} + static class TestTraceService extends TraceServiceGrpc.TraceServiceImplBase { + } void awaitCallbackResult() throws Throwable { AtomicReference ref = new AtomicReference<>(); CountDownLatch latch = new CountDownLatch(1); call.enqueue( - new Callback() { - @Override - public void onSuccess(Empty empty) { - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - ref.set(throwable); - latch.countDown(); - } - }); + new Callback() { + @Override + public void onSuccess(Empty empty) { + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + ref.set(throwable); + latch.countDown(); + } + }); latch.await(10, TimeUnit.MILLISECONDS); if (ref.get() != null) throw ref.get(); } void onClientCall(Consumer> onClientCall) { doAnswer( - (Answer) - invocationOnMock -> { - StreamObserver observer = - ((StreamObserver) invocationOnMock.getArguments()[1]); - onClientCall.accept(observer); - return null; - }) - .when(traceService) - .batchWriteSpans(any(BatchWriteSpansRequest.class), any(StreamObserver.class)); + (Answer) + invocationOnMock -> { + StreamObserver observer = + ((StreamObserver) invocationOnMock.getArguments()[1]); + onClientCall.accept(observer); + return null; + }) + .when(traceService) + .batchWriteSpans(any(BatchWriteSpansRequest.class), any(StreamObserver.class)); } } diff --git a/storage-stackdriver/pom.xml b/storage-stackdriver/pom.xml index 9308f322..183aacb9 100644 --- a/storage-stackdriver/pom.xml +++ b/storage-stackdriver/pom.xml @@ -53,6 +53,13 @@ ${protobuf.version} + + ${zipkin.groupId} + zipkin-tests + ${zipkin.version} + test + + ${armeria.groupId} armeria-grpc @@ -62,7 +69,7 @@ ${armeria.groupId} - armeria-junit4 + armeria-junit5 ${armeria.version} test diff --git a/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/StackdriverSpanConsumerTest.java b/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/StackdriverSpanConsumerTest.java index 3bc9f13b..094dd001 100644 --- a/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/StackdriverSpanConsumerTest.java +++ b/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/StackdriverSpanConsumerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -19,15 +19,16 @@ import com.linecorp.armeria.common.grpc.protocol.ArmeriaStatusException; import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.grpc.GrpcService; -import com.linecorp.armeria.testing.junit4.server.ServerRule; +import com.linecorp.armeria.testing.junit5.server.ServerExtension; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import java.util.Collections; import java.util.function.Consumer; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; import zipkin2.CheckResult; @@ -44,11 +45,12 @@ import static org.mockito.Mockito.verify; /** Same as AsyncReporterStackdriverSenderTest: tests everything wired together */ -public class StackdriverSpanConsumerTest { +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class StackdriverSpanConsumerTest { final TestTraceService traceService = spy(new TestTraceService()); - @Rule public final ServerRule server = new ServerRule() { + @RegisterExtension ServerExtension server = new ServerExtension() { @Override protected void configure(ServerBuilder sb) { sb.service(GrpcService.builder() .addService(traceService) @@ -60,23 +62,21 @@ public class StackdriverSpanConsumerTest { StackdriverStorage storage; SpanConsumer spanConsumer; - @Before - public void setUp() { + @BeforeEach + void setUp() { storage = StackdriverStorage.newBuilder("http://localhost:" + server.httpPort()) .projectId(projectId) .build(); spanConsumer = storage.spanConsumer(); } - @Test - public void accept_empty() throws Exception { + @Test void accept_empty() throws Exception { spanConsumer.accept(Collections.emptyList()).execute(); verify(traceService, never()).batchWriteSpans(any(), any()); } - @Test - public void accept() throws Exception { + @Test void accept() throws Exception { onClientCall( observer -> { observer.onNext(Empty.getDefaultInstance()); @@ -96,8 +96,7 @@ public void accept() throws Exception { .isEqualTo(SpanTranslator.translate(projectId, asList(TestObjects.CLIENT_SPAN))); } - @Test - public void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { + @Test void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { onClientCall(observer -> { observer.onError(new StatusRuntimeException(Status.RESOURCE_EXHAUSTED)); }); @@ -111,8 +110,7 @@ public void verifyCheckReturnsFailureWhenServiceFailsWithKnownGrpcFailure() { .isEqualTo(Status.RESOURCE_EXHAUSTED.getCode().value())); } - @Test - public void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { + @Test void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { onClientCall(observer -> { observer.onError(new RuntimeException("oh no")); }); @@ -125,16 +123,14 @@ public void verifyCheckReturnsFailureWhenServiceFailsForUnknownReason() { .isEqualTo(Status.UNKNOWN.getCode().value())); } - @Test - public void verifyCheckReturnsOkWhenExpectedValidationFailure() { + @Test void verifyCheckReturnsOkWhenExpectedValidationFailure() { onClientCall(observer -> { observer.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT)); }); assertThat(storage.check()).isSameAs(CheckResult.OK); } - @Test - public void verifyCheckReturnsOkWhenServiceSucceeds() { + @Test void verifyCheckReturnsOkWhenServiceSucceeds() { onClientCall(observer -> { observer.onNext(Empty.getDefaultInstance()); observer.onCompleted(); diff --git a/translation-stackdriver/pom.xml b/translation-stackdriver/pom.xml index 596ff486..8de3035b 100644 --- a/translation-stackdriver/pom.xml +++ b/translation-stackdriver/pom.xml @@ -40,7 +40,7 @@ com.google.api.grpc proto-google-common-protos - 2.0.1 + 2.29.0 diff --git a/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanTranslator.java b/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanTranslator.java index 3ee79c6a..4a6af64e 100644 --- a/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanTranslator.java +++ b/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -47,8 +47,8 @@ public final class SpanTranslator { /** * Convert a Collection of Zipkin Spans into a Collection of Stackdriver Trace Spans. * - * @param projectId The Google Cloud Platform projectId that should be used for Stackdriver Trace - * Traces. + * @param projectId The Google Cloud Platform projectId that should be used for Stackdriver Trace + * Traces. * @param zipkinSpans The Collection of Zipkin Spans. * @return A Collection of Stackdriver Trace Spans. */ @@ -82,7 +82,7 @@ public static List translate( * and it is up to callers to make sure to fill it using the project ID and trace ID. * * @param spanBuilder the builder (to facilitate re-use) - * @param zipkinSpan The Zipkin Span. + * @param zipkinSpan The Zipkin Span. * @return A Stackdriver Trace Span. */ public static com.google.devtools.cloudtrace.v2.Span.Builder translate( @@ -92,14 +92,16 @@ public static com.google.devtools.cloudtrace.v2.Span.Builder translate( if (logTranslation) LOG.log(FINE, ">> translating zipkin span: {0}", zipkinSpan); spanBuilder.setSpanId(zipkinSpan.id()); - if (zipkinSpan.parentId() != null ) { + if (zipkinSpan.parentId() != null) { spanBuilder.setParentSpanId(zipkinSpan.parentId()); } // NOTE: opencensus prefixes Send. and Recv. based on Kind. For now we reproduce our V1 behavior // of using the span name as the display name as is. spanBuilder.setDisplayName( - toTruncatableString((zipkinSpan.name() != null && !zipkinSpan.name().isEmpty()) ? zipkinSpan.name() : "unknown")); + toTruncatableString( + (zipkinSpan.name() != null && !zipkinSpan.name().isEmpty()) ? zipkinSpan.name() + : "unknown")); if (zipkinSpan.timestampAsLong() != 0L) { spanBuilder.setStartTime(createTimestamp(zipkinSpan.timestampAsLong())); diff --git a/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanUtil.java b/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanUtil.java index 64a2355a..a3d9f73e 100644 --- a/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanUtil.java +++ b/translation-stackdriver/src/main/java/zipkin2/translation/stackdriver/SpanUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -30,5 +30,6 @@ static TruncatableString toTruncatableString(String string) { return TruncatableString.newBuilder().setValue(string).setTruncatedByteCount(0).build(); } - private SpanUtil() {} + private SpanUtil() { + } } diff --git a/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/AttributesExtractorTest.java b/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/AttributesExtractorTest.java index 49844c3b..d9d1f015 100644 --- a/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/AttributesExtractorTest.java +++ b/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/AttributesExtractorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -17,7 +17,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import zipkin2.Endpoint; import zipkin2.Span; import zipkin2.Span.Kind; @@ -27,8 +27,7 @@ import static zipkin2.translation.stackdriver.AttributesExtractor.toAttributeValue; public class AttributesExtractorTest { - @Test - public void testLabel() { + @Test void testLabel() { AttributesExtractor extractor = new AttributesExtractor(Collections.emptyMap()); Span zipkinSpan = Span.newBuilder() @@ -42,8 +41,7 @@ public void testLabel() { assertThat(labels).contains(entry("tag.key.1", toAttributeValue("value"))); } - @Test - public void testLabelIsRenamed() { + @Test void testLabelIsRenamed() { Map knownLabels = new LinkedHashMap<>(); knownLabels.put("known.1", "renamed.1"); knownLabels.put("known.2", "renamed.2"); @@ -62,8 +60,7 @@ public void testLabelIsRenamed() { assertThat(labels).contains(entry("renamed.2", toAttributeValue("known.value"))); } - @Test - public void testAgentLabelIsSet() { + @Test void testAgentLabelIsSet() { AttributesExtractor extractor = new AttributesExtractor(Collections.emptyMap()); Span rootSpan = Span.newBuilder().traceId("4").name("test-span").id("5").build(); Span nonRootSpan = @@ -80,8 +77,7 @@ public void testAgentLabelIsSet() { System.clearProperty("stackdriver.trace.zipkin.agent"); } - @Test - public void testEndpointIsSetIpv4() { + @Test void testEndpointIsSetIpv4() { Endpoint.Builder serverEndpointBuilder = Endpoint.newBuilder().serviceName("service1").port(80); serverEndpointBuilder.parseIp("10.0.0.1"); Endpoint serverEndpoint = serverEndpointBuilder.build(); @@ -114,8 +110,7 @@ public void testEndpointIsSetIpv4() { assertThat(clientLabels).doesNotContainKeys("endpoint.ipv4", "endpoint.ipv6"); } - @Test - public void testEndpointIsSetIpv6() { + @Test void testEndpointIsSetIpv6() { Endpoint.Builder serverEndpointBuilder = Endpoint.newBuilder().serviceName("service1").port(80); serverEndpointBuilder.parseIp("::1"); Endpoint serverEndpoint = serverEndpointBuilder.build(); @@ -148,8 +143,7 @@ public void testEndpointIsSetIpv6() { assertThat(clientLabels).doesNotContainKeys("endpoint.ipv4", "endpoint.ipv6"); } - @Test - public void testEndpointWithNullServiceName() { + @Test void testEndpointWithNullServiceName() { Endpoint.Builder serverEndpointBuilder = Endpoint.newBuilder().port(80); Endpoint serverEndpoint = serverEndpointBuilder.build(); Span serverSpan = @@ -166,8 +160,7 @@ public void testEndpointWithNullServiceName() { assertThat(serverLabels).doesNotContainKey("endpoint.serviceName"); } - @Test - public void testComponentLabelIsSet() { + @Test void testComponentLabelIsSet() { AttributesExtractor extractor = new AttributesExtractor(Collections.emptyMap()); Span clientSpan = Span.newBuilder() diff --git a/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/SpanTranslatorTest.java b/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/SpanTranslatorTest.java index d26d4a94..115b0891 100644 --- a/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/SpanTranslatorTest.java +++ b/translation-stackdriver/src/test/java/zipkin2/translation/stackdriver/SpanTranslatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The OpenZipkin Authors + * Copyright 2016-2023 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import zipkin2.Endpoint; import zipkin2.Span; @@ -29,8 +29,7 @@ public class SpanTranslatorTest { /** This test is intentionally sensitive, so changing other parts makes obvious impact here */ - @Test - public void translate_clientSpan() { + @Test void translate_clientSpan() { Span zipkinSpan = Span.newBuilder() .traceId("7180c278b62e8f6a216a2aea45d08fc9") @@ -82,8 +81,7 @@ public void translate_clientSpan() { .build()); } - @Test - public void translate_missingName() { + @Test void translate_missingName() { Span zipkinSpan = Span.newBuilder().traceId("3").id("2").build(); com.google.devtools.cloudtrace.v2.Span translated = SpanTranslator.translate( com.google.devtools.cloudtrace.v2.Span.newBuilder(), zipkinSpan).build(); @@ -91,8 +89,7 @@ public void translate_missingName() { assertThat(translated.getDisplayName().getValue()).isNotEmpty(); } - @Test - public void testTranslateSpans() { + @Test void testTranslateSpans() { Span span1 = Span.newBuilder().id("1").traceId("1").name("/a").timestamp(1L).duration(1L).build(); Span span2 = @@ -112,8 +109,7 @@ public void testTranslateSpans() { "projects/test-project/traces/00000000000000000000000000000001/spans/0000000000000003"); } - @Test - public void testTranslateSpanEmptyName() { + @Test void testTranslateSpanEmptyName() { Span spanNullName = Span.newBuilder().id("1").traceId("1").timestamp(1L).duration(1L).build(); Span spanEmptyName =