From 25c92fb6ac7169aa05c95511171210ceaa78cc02 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Tue, 22 Nov 2022 12:58:44 -0600 Subject: [PATCH 1/9] Remove outdated todo (#4978) --- .../exporter/internal/otlp/logs/ResourceLogsMarshaler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/ResourceLogsMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/ResourceLogsMarshaler.java index 4e2ee16e7e1..76767e8266e 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/ResourceLogsMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/ResourceLogsMarshaler.java @@ -96,8 +96,6 @@ private static int calculateSize( groupByResourceAndScope(Collection logs) { return MarshalerUtil.groupByResourceAndScope( logs, - // TODO(anuraaga): Replace with an internal SdkData type of interface that exposes these - // two. LogRecordData::getResource, LogRecordData::getInstrumentationScopeInfo, LogMarshaler::create); From f6deb4c1b7b9ed250f3f7cda992a012b6e738af2 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Tue, 22 Nov 2022 13:55:27 -0600 Subject: [PATCH 2/9] Remove japicmp exception for log SDK changes (#4977) --- .../otel.japicmp-conventions.gradle.kts | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts index ab182cb40de..37b176efb7b 100644 --- a/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts @@ -1,9 +1,7 @@ import com.google.auto.value.AutoValue import japicmp.model.JApiChangeStatus -import japicmp.model.JApiClass import japicmp.model.JApiCompatibility import japicmp.model.JApiCompatibilityChange -import japicmp.model.JApiConstructor import japicmp.model.JApiMethod import me.champeau.gradle.japicmp.JapicmpTask import me.champeau.gradle.japicmp.report.Severity @@ -40,9 +38,6 @@ class AllowDefaultMethodRule : AbstractRecordingSeenMembers() { if (isAbstractMethodOnAutoValue(member, change)) { continue } - if (isLogRename(member)) { - continue - } if (!change.isSourceCompatible) { return Violation.error(member, "Not source compatible") } @@ -64,35 +59,6 @@ class AllowDefaultMethodRule : AbstractRecordingSeenMembers() { member is JApiMethod && member.getjApiClass().newClass.get().getAnnotation(AutoValue::class.java) != null } - - /** - * Check if the change is related to log related renames. - */ - // TODO(jack-berg): remove after 1.19.0. - fun isLogRename(member: JApiCompatibility): Boolean { - try { - if (member is JApiMethod) { - val longName = member.oldMethod.get().longName - return longName.matches(".*OpenTelemetrySdk\\.getSdkLogEmitterProvider.*".toRegex()) || - longName.matches(".*OpenTelemetrySdkBuilder\\.setLogEmitterProvider.*".toRegex()) || - longName.matches(".*AutoConfigurationCustomizer\\.addLogExporterCustomizer.*".toRegex()) || - longName.matches(".*AutoConfigurationCustomizer\\.addLogEmitterProviderCustomizer.*".toRegex()) || - longName.matches(".*ConfigurableLogExporterProvider.*".toRegex()) || - longName.matches(".*SystemOutLogExporter.*".toRegex()) || - longName.matches(".*OtlpJsonLoggingLogExporter.*".toRegex()) - } else if (member is JApiClass) { - val fqcn = member.fullyQualifiedName - return fqcn.matches(".*SystemOutLogExporter".toRegex()) || - fqcn.matches(".*ConfigurableLogExporterProvider".toRegex()) || - fqcn.matches(".*OtlpJsonLoggingLogExporter".toRegex()) - } else if (member is JApiConstructor) { - return member.oldConstructor.get().longName.matches(".*SystemOutLogExporter.*".toRegex()) - } - return false - } catch (e: IllegalStateException) { - return false - } - } } /** From 41c5fbc19a508d41f46f0d2f3d7aa3df9fd4c9d5 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Thu, 24 Nov 2022 19:53:09 +0100 Subject: [PATCH 3/9] OpenTracing Shim: Properly set the status based on the error tag. (#4962) --- .../opentracingshim/SpanBuilderShim.java | 6 +- .../opentracingshim/SpanShim.java | 4 +- .../opentracingshim/SpanBuilderShimTest.java | 68 +++++++++++++++++++ .../opentracingshim/SpanShimTest.java | 28 ++++++++ 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java index ac3c1f62c17..2551e83d7d8 100644 --- a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java +++ b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java @@ -44,7 +44,7 @@ final class SpanBuilderShim extends BaseShimObject implements SpanBuilder { private final List spanBuilderAttributeValues = new ArrayList<>(); @Nullable private SpanKind spanKind; - private boolean error; + @Nullable private Boolean error; private long startTimestampMicros; private static final Attributes CHILD_OF_ATTR = @@ -249,8 +249,8 @@ public Span start() { } io.opentelemetry.api.trace.Span span = builder.startSpan(); - if (error) { - span.setStatus(StatusCode.ERROR); + if (error != null) { + span.setStatus(error ? StatusCode.ERROR : StatusCode.OK); } return new SpanShim(telemetryInfo(), span, baggage); diff --git a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanShim.java b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanShim.java index 10adf19adf5..c12858c72ff 100644 --- a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanShim.java +++ b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanShim.java @@ -86,7 +86,7 @@ public Span setTag(String key, String value) { // TODO: confirm we can safely ignore span.kind after Span was created // https://github.com/bogdandrutu/opentelemetry/issues/42 } else if (Tags.ERROR.getKey().equals(key)) { - StatusCode canonicalCode = Boolean.parseBoolean(value) ? StatusCode.ERROR : StatusCode.UNSET; + StatusCode canonicalCode = Boolean.parseBoolean(value) ? StatusCode.ERROR : StatusCode.OK; span.setStatus(canonicalCode); } else { span.setAttribute(key, value); @@ -98,7 +98,7 @@ public Span setTag(String key, String value) { @Override public Span setTag(String key, boolean value) { if (Tags.ERROR.getKey().equals(key)) { - StatusCode canonicalCode = value ? StatusCode.ERROR : StatusCode.UNSET; + StatusCode canonicalCode = value ? StatusCode.ERROR : StatusCode.OK; span.setStatus(canonicalCode); } else { span.setAttribute(key, value); diff --git a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java index 16ff9cfeb99..a915cee1272 100644 --- a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java +++ b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; @@ -18,10 +19,12 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingResult; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import io.opentracing.References; +import io.opentracing.tag.Tags; import java.math.BigInteger; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -41,6 +44,23 @@ void setUp() { GlobalOpenTelemetry.resetForTest(); } + @Test + void default_values() { + SpanShim span = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start(); + try { + SpanData spanData = ((ReadableSpan) span.getSpan()).toSpanData(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getStatus()).isEqualTo(StatusData.unset()); + assertThat(spanData.getSpanContext()).isNotEqualTo(SpanContext.getInvalid()); + assertThat(spanData.getKind()).isEqualTo(SpanKind.INTERNAL); + assertThat(spanData.getAttributes().size()).isEqualTo(0); + assertThat(spanData.getEvents()).hasSize(0); + assertThat(spanData.getLinks()).hasSize(0); + } finally { + span.finish(); + } + } + @Test void parent_single() { SpanShim parentSpan = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start(); @@ -297,6 +317,54 @@ void withStartTimestamp() { assertThat(spanData.getStartEpochNanos()).isEqualTo(micros * 1000L); } + @Test + void setAttribute_errorAsBoolean() { + SpanShim span1 = + (SpanShim) + new SpanBuilderShim(telemetryInfo, SPAN_NAME) + .withTag(Tags.ERROR.getKey(), true) + .start(); + SpanShim span2 = + (SpanShim) + new SpanBuilderShim(telemetryInfo, SPAN_NAME) + .withTag(Tags.ERROR.getKey(), false) + .start(); + try { + SpanData spanData1 = ((ReadableSpan) span1.getSpan()).toSpanData(); + assertThat(spanData1.getStatus()).isEqualTo(StatusData.error()); + + SpanData spanData2 = ((ReadableSpan) span2.getSpan()).toSpanData(); + assertThat(spanData2.getStatus()).isEqualTo(StatusData.ok()); + } finally { + span1.finish(); + span2.finish(); + } + } + + @Test + void setAttribute_errorAsString() { + SpanShim span1 = + (SpanShim) + new SpanBuilderShim(telemetryInfo, SPAN_NAME) + .withTag(Tags.ERROR.getKey(), "tRuE") + .start(); + SpanShim span2 = + (SpanShim) + new SpanBuilderShim(telemetryInfo, SPAN_NAME) + .withTag(Tags.ERROR.getKey(), "FaLsE") + .start(); + try { + SpanData spanData1 = ((ReadableSpan) span1.getSpan()).toSpanData(); + assertThat(spanData1.getStatus()).isEqualTo(StatusData.error()); + + SpanData spanData2 = ((ReadableSpan) span2.getSpan()).toSpanData(); + assertThat(spanData2.getStatus()).isEqualTo(StatusData.ok()); + } finally { + span1.finish(); + span2.finish(); + } + } + @Test void setAttribute_unrecognizedType() { SpanShim span = diff --git a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java index 1d304e04c32..66b9a21be25 100644 --- a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java +++ b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java @@ -15,8 +15,10 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.data.EventData; import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import io.opentracing.log.Fields; +import io.opentracing.tag.Tags; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; @@ -60,6 +62,32 @@ void context_simple() { assertThat(contextShim.baggageItems().iterator().hasNext()).isFalse(); } + @Test + void setAttribute_errorAsBoolean() { + SpanShim spanShim = new SpanShim(telemetryInfo, span); + spanShim.setTag(Tags.ERROR.getKey(), true); + + SpanData spanData = ((ReadableSpan) span).toSpanData(); + assertThat(spanData.getStatus()).isEqualTo(StatusData.error()); + + spanShim.setTag(Tags.ERROR.getKey(), false); + spanData = ((ReadableSpan) span).toSpanData(); + assertThat(spanData.getStatus()).isEqualTo(StatusData.ok()); + } + + @Test + void setAttribute_errorAsString() { + SpanShim spanShim = new SpanShim(telemetryInfo, span); + spanShim.setTag(Tags.ERROR.getKey(), "tRuE"); + + SpanData spanData = ((ReadableSpan) span).toSpanData(); + assertThat(spanData.getStatus()).isEqualTo(StatusData.error()); + + spanShim.setTag(Tags.ERROR.getKey(), "FaLsE"); + spanData = ((ReadableSpan) span).toSpanData(); + assertThat(spanData.getStatus()).isEqualTo(StatusData.ok()); + } + @Test void setAttribute_unrecognizedType() { SpanShim spanShim = new SpanShim(telemetryInfo, span); From c8a382618eea6d8e7defd266c2a39098401065e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 13:06:56 -0800 Subject: [PATCH 4/9] Bump com.diffplug.spotless from 6.11.0 to 6.12.0 (#4986) Bumps com.diffplug.spotless from 6.11.0 to 6.12.0. --- updated-dependencies: - dependency-name: com.diffplug.spotless dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 218a42d1c24..4a483ed5f35 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -2,7 +2,7 @@ plugins { `kotlin-dsl` // When updating, update below in dependencies too - id("com.diffplug.spotless") version "6.11.0" + id("com.diffplug.spotless") version "6.12.0" } repositories { From 1209826ef1dc4e829f0b2b9c5e2b9af799e6cf7c Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 25 Nov 2022 13:11:32 -0800 Subject: [PATCH 5/9] GitHub actions sync (#4966) * Sync * Sync * chmod * Fix misspelling --- .../markdown-link-check-config.json | 0 .github/scripts/draft-change-log-entries.sh | 34 +++++++ .../scripts/markdown-link-check-with-retry.sh | 2 +- .../scripts/merge-change-log-after-release.sh | 44 +++++++++ .github/workflows/backport.yml | 6 +- .github/workflows/build.yml | 19 ++-- .github/workflows/codeql-daily.yml | 6 +- .github/workflows/prepare-patch-release.yml | 6 +- .github/workflows/prepare-release-branch.yml | 21 ++-- .github/workflows/release.yml | 98 ++++++++----------- .github/workflows/reusable-misspell-check.yml | 2 +- .../reusable-open-issue-on-failure.yml | 4 +- 12 files changed, 150 insertions(+), 92 deletions(-) rename .github/{scripts => config}/markdown-link-check-config.json (100%) create mode 100755 .github/scripts/draft-change-log-entries.sh create mode 100755 .github/scripts/merge-change-log-after-release.sh diff --git a/.github/scripts/markdown-link-check-config.json b/.github/config/markdown-link-check-config.json similarity index 100% rename from .github/scripts/markdown-link-check-config.json rename to .github/config/markdown-link-check-config.json diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh new file mode 100755 index 00000000000..d62f210bfe9 --- /dev/null +++ b/.github/scripts/draft-change-log-entries.sh @@ -0,0 +1,34 @@ +#!/bin/bash -e + +version=$("$(dirname "$0")/get-version.sh") + +if [[ $version =~ ([0-9]+)\.([0-9]+)\.0 ]]; then + major="${BASH_REMATCH[1]}" + minor="${BASH_REMATCH[2]}" +else + echo "unexpected version: $version" + exit 1 +fi + +if [[ $minor == 0 ]]; then + prior_major=$((major - 1)) + prior_minor=$(sed -n "s/^## Version $prior_major\.\([0-9]\+\)\..*/\1/p" CHANGELOG.md | head -1) + if [[ -z $prior_minor ]]; then + # assuming this is the first release + range= + else + range="v$prior_major.$prior_minor.0..HEAD" + fi +else + range="v$major.$((minor - 1)).0..HEAD" +fi + +echo "## Unreleased" +echo + +git log --reverse \ + --perl-regexp \ + --author='^(?!dependabot\[bot\] )' \ + --pretty=format:"- %s" \ + "$range" \ + | sed -E 's,\(#([0-9]+)\)$,\n ([#\1](https://github.com/open-telemetry/opentelemetry-java/pull/\1)),' diff --git a/.github/scripts/markdown-link-check-with-retry.sh b/.github/scripts/markdown-link-check-with-retry.sh index 109146abfec..9a81e8df95b 100755 --- a/.github/scripts/markdown-link-check-with-retry.sh +++ b/.github/scripts/markdown-link-check-with-retry.sh @@ -6,7 +6,7 @@ retry_count=3 for file in "$@"; do for i in $(seq 1 $retry_count); do - if markdown-link-check --config "$(dirname "$0")/markdown-link-check-config.json" \ + if markdown-link-check --config "$(dirname "$0")/../config/markdown-link-check-config.json" \ "$file"; then break elif [[ $i -eq $retry_count ]]; then diff --git a/.github/scripts/merge-change-log-after-release.sh b/.github/scripts/merge-change-log-after-release.sh new file mode 100755 index 00000000000..1b95eeb8cb4 --- /dev/null +++ b/.github/scripts/merge-change-log-after-release.sh @@ -0,0 +1,44 @@ +#!/bin/bash -e + +# this script merges release notes for $VERSION into CHANGELOG.md +# the release date for $VERSION should be available in $RELEASE_DATE +# and the release notes for $VERSION should be available in /tmp/changelog-section.md + +if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.0 ]]; then + # this was not a patch release, so the version exists already in the CHANGELOG.md + + # update the release date + sed -Ei "s/## Version $VERSION .*/## Version $VERSION ($RELEASE_DATE)/" CHANGELOG.md + + # the entries are copied over from the release branch to support workflows + # where change log entries may be updated after preparing the release branch + + { + # copy the portion above the release, up to and including the heading + sed -n "0,/^## Version $VERSION /p" CHANGELOG.md + # copy the release notes for $VERSION + cat /tmp/changelog-section.md + # copy the portion below the release + sed -n "0,/^## Version $VERSION /d;0,/^## Version /{/^## Version/!d};p" CHANGELOG.md + } > /tmp/CHANGELOG.md + + # update the real CHANGELOG.md + cp /tmp/CHANGELOG.md CHANGELOG.md + +else + # this was a patch release, so the version does not exist already in the CHANGELOG.md + + { + # copy the portion above the top-most release, not including the heading + sed -n "0,/^## Version /{ /^## Version /!p }" CHANGELOG.md + # add the heading + echo "## Version $VERSION ($RELEASE_DATE)" + # copy the release notes for $VERSION + cat /tmp/changelog-section.md + # copy the portion starting from the top-most release + sed -n "/^## Version /,\$p" CHANGELOG.md + } > /tmp/CHANGELOG.md + + # update the real CHANGELOG.md + cp /tmp/CHANGELOG.md CHANGELOG.md +fi diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 2759b639876..fcff72284da 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -28,16 +28,16 @@ jobs: env: NUMBER: ${{ github.event.inputs.number }} # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + GH_TOKEN: ${{ secrets.BOT_TOKEN }} run: | commit=$(gh pr view $NUMBER --json mergeCommit --jq .mergeCommit.oid) title=$(gh pr view $NUMBER --json title --jq .title) branch="opentelemetrybot/backport-${NUMBER}-to-${GITHUB_REF_NAME//\//-}" + git checkout -b $branch git cherry-pick $commit - git push origin HEAD:$branch + git push --set-upstream origin $branch gh pr create --title "[$GITHUB_REF_NAME] $title" \ --body "Clean cherry-pick of #$NUMBER to the \`$GITHUB_REF_NAME\` branch." \ - --head $branch \ --base $GITHUB_REF_NAME diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7b7d6d44e3..d79e5f227c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,8 +34,6 @@ jobs: coverage: true steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - id: setup-java-test name: Set up Java ${{ matrix.test-java-version }} for tests @@ -85,13 +83,12 @@ jobs: path: all/build/reports/jacoco/test/html markdown-link-check: - # release branches are excluded to avoid unnecessary maintenance if external links break + # release branches are excluded to avoid unnecessary maintenance if: ${{ !startsWith(github.ref_name, 'release/') }} uses: ./.github/workflows/reusable-markdown-link-check.yml misspell-check: - # release branches are excluded to avoid unnecessary maintenance if new misspellings are added - # to the misspell dictionary + # release branches are excluded to avoid unnecessary maintenance if: ${{ !startsWith(github.ref_name, 'release/') }} uses: ./.github/workflows/reusable-misspell-check.yml @@ -111,8 +108,6 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - id: setup-java name: Set up Java @@ -134,11 +129,11 @@ jobs: GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} required-status-check: - # markdown-link-check is not required so that pull requests will not be blocked if external - # links break - # similarly misspell-check is not required so that pull requests will not be blocked if new - # misspellings are added to the misspell dictionary - needs: build + # markdown-link-check is not required so pull requests are not blocked if external links break + # misspell-check is not required so pull requests are not blocked if the misspell dictionary is + # updated + needs: + - build runs-on: ubuntu-latest if: always() steps: diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index bb1ef7afe51..bbd44ad27f4 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -2,6 +2,7 @@ name: CodeQL (daily) on: schedule: + # Daily at 01:30 (UTC) - cron: '30 1 * * *' workflow_dispatch: @@ -33,6 +34,7 @@ jobs: open-issue-on-failure: # open an issue on failure because it can be easy to miss CI failure notifications - needs: analyze - if: failure() + needs: + - analyze + if: failure() && github.run_attempt == 1 uses: ./.github/workflows/reusable-open-issue-on-failure.yml diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml index ac3b621770a..37c03918084 100644 --- a/.github/workflows/prepare-patch-release.yml +++ b/.github/workflows/prepare-patch-release.yml @@ -45,14 +45,14 @@ jobs: - name: Create pull request env: # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + GH_TOKEN: ${{ secrets.BOT_TOKEN }} run: | message="Prepare release $VERSION" branch="opentelemetrybot/prepare-release-${VERSION}" + git checkout -b $branch git commit -a -m "$message" - git push origin HEAD:$branch + git push --set-upstream origin $branch gh pr create --title "[$GITHUB_REF_NAME] $message" \ --body "$message." \ - --head $branch \ --base $GITHUB_REF_NAME diff --git a/.github/workflows/prepare-release-branch.yml b/.github/workflows/prepare-release-branch.yml index 6569c043430..41e718c2b5e 100644 --- a/.github/workflows/prepare-release-branch.yml +++ b/.github/workflows/prepare-release-branch.yml @@ -8,7 +8,8 @@ jobs: steps: - uses: actions/checkout@v3 - - run: | + - name: Verify prerequisites + run: | if [[ $GITHUB_REF_NAME != main ]]; then echo this workflow should only be run against main exit 1 @@ -21,7 +22,8 @@ jobs: create-pull-request-against-release-branch: runs-on: ubuntu-latest - needs: prereqs + needs: + - prereqs steps: - uses: actions/checkout@v3 @@ -55,21 +57,22 @@ jobs: - name: Create pull request against the release branch env: # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + GH_TOKEN: ${{ secrets.BOT_TOKEN }} run: | message="Prepare release $VERSION" branch="opentelemetrybot/prepare-release-${VERSION}" + git checkout -b $branch git commit -a -m "$message" - git push origin HEAD:$branch + git push --set-upstream origin $branch gh pr create --title "[$RELEASE_BRANCH_NAME] $message" \ --body "$message." \ - --head $branch \ --base $RELEASE_BRANCH_NAME create-pull-request-against-main: runs-on: ubuntu-latest - needs: prereqs + needs: + - prereqs steps: - uses: actions/checkout@v3 @@ -102,15 +105,15 @@ jobs: - name: Create pull request against main env: # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + GH_TOKEN: ${{ secrets.BOT_TOKEN }} run: | message="Update version to $NEXT_VERSION" body="Update version to \`$NEXT_VERSION\`." branch="opentelemetrybot/update-version-to-${NEXT_VERSION}" + git checkout -b $branch git commit -a -m "$message" - git push origin HEAD:$branch + git push --set-upstream origin $branch gh pr create --title "$message" \ --body "$body" \ - --head $branch \ --base main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc3e19e101f..c7792090efd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,13 +4,13 @@ on: jobs: release: + runs-on: ubuntu-20.04 outputs: version: ${{ steps.create-github-release.outputs.version }} - runs-on: ubuntu-20.04 steps: - run: | if [[ $GITHUB_REF_NAME != release/* ]]; then - echo the release workflow should only be run against release branches + echo this workflow should only be run against release branches exit 1 fi @@ -62,7 +62,8 @@ jobs: with: ref: main - - run: | + - name: Check that change log update was merged to main + run: | if [[ $VERSION == *.0 ]]; then # not making a patch release if ! grep --quiet "^## Version $VERSION " CHANGELOG.md; then @@ -79,7 +80,7 @@ jobs: - name: Generate release notes env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # conditional blocks not indented because of the heredoc if [[ $VERSION != *.0 ]]; then @@ -114,7 +115,7 @@ jobs: - id: create-github-release name: Create GitHub release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release create --target $GITHUB_REF_NAME \ --title "Version $VERSION" \ @@ -124,81 +125,60 @@ jobs: echo "::set-output name=version::$VERSION" + merge-change-log-to-main: + runs-on: ubuntu-latest + needs: + - release + steps: - uses: actions/checkout@v3 - with: - # the step below is creating a pull request against main - ref: main - - name: Copy change log updates to main + - name: Copy change log section from release branch env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ needs.release.outputs.version }} run: | - if [[ $VERSION == *.0 ]]; then - # this was not a patch release, so the version exists already in the CHANGELOG.md - - # update the release date - date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') - sed -Ei "s/## Version $VERSION .*/## Version $VERSION ($date)/" CHANGELOG.md - - # the entries are copied over from the release branch to support workflows - # where change log entries may be updated after preparing the release branch - - # copy the portion above the release, up to and including the heading - sed -n "0,/^## Version $VERSION ($date)/p" CHANGELOG.md > /tmp/CHANGELOG.md - - # copy the release notes - cat /tmp/CHANGELOG_SECTION.md >> /tmp/CHANGELOG.md - - # copy the portion below the release - sed -n "0,/^## Version $VERSION /d;0,/^## Version /{/^## Version/!d};p" CHANGELOG.md \ - >> /tmp/CHANGELOG.md - - # update the real CHANGELOG.md - cp /tmp/CHANGELOG.md CHANGELOG.md - else - # this was a patch release, so the version does not exist already in the CHANGELOG.md - - # copy the portion above the top-most release, not including the heading - sed -n "0,/^## Version /{ /^## Version /!p }" CHANGELOG.md > /tmp/CHANGELOG.md - - # add the heading - date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') - echo "## Version $VERSION ($date)" >> /tmp/CHANGELOG.md - - # copy the release notes - cat /tmp/CHANGELOG_SECTION.md >> /tmp/CHANGELOG.md + sed -n "0,/^## Version $VERSION /d;/^## Version /q;p" CHANGELOG.md \ + > /tmp/changelog-section.md - # copy the portion starting from the top-most release - sed -n "/^## Version /,\$p" CHANGELOG.md >> /tmp/CHANGELOG.md + - uses: actions/checkout@v3 + with: + ref: main - # update the real CHANGELOG.md - cp /tmp/CHANGELOG.md CHANGELOG.md - fi + - name: Merge change log to main + env: + VERSION: ${{ needs.release.outputs.version }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + release_date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') + RELEASE_DATE=$release_date .github/scripts/merge-change-log-after-release.sh - name: Use CLA approved github bot run: .github/scripts/use-cla-approved-github-bot.sh - name: Create pull request against main env: + VERSION: ${{ needs.release.outputs.version }} # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + GH_TOKEN: ${{ secrets.BOT_TOKEN }} run: | - message="Copy change log updates from $GITHUB_REF_NAME" - body="Copy log updates from \`$GITHUB_REF_NAME\`." - branch="opentelemetrybot/copy-change-log-updates-from-${GITHUB_REF_NAME//\//-}" - - if [[ $VERSION == *.0 ]]; then - if git diff --quiet; then - echo there are no updates needed to the change log on main, not creating pull request + if git diff --quiet; then + if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.0 ]]; then + echo there are no updates to merge, not creating pull request exit 0 # success + else + echo patch release notes did not get applied for some reason + exit 1 # failure fi fi + message="Merge change log updates from $GITHUB_REF_NAME" + body="Merge log updates from \`$GITHUB_REF_NAME\`." + branch="opentelemetrybot/merge-change-log-updates-from-${GITHUB_REF_NAME//\//-}" + + git checkout -b $branch git commit -a -m "$message" - git push origin HEAD:$branch + git push --set-upstream origin $branch gh pr create --title "$message" \ --body "$body" \ - --head $branch \ --base main create-website-pull-request: diff --git a/.github/workflows/reusable-misspell-check.yml b/.github/workflows/reusable-misspell-check.yml index 24f3a2c71be..105649c8197 100644 --- a/.github/workflows/reusable-misspell-check.yml +++ b/.github/workflows/reusable-misspell-check.yml @@ -11,7 +11,7 @@ jobs: - name: Install misspell run: | - curl -L -o ./install-misspell.sh https://git.io/misspell + curl -L -o install-misspell.sh https://git.io/misspell sh ./install-misspell.sh - name: Run misspell diff --git a/.github/workflows/reusable-open-issue-on-failure.yml b/.github/workflows/reusable-open-issue-on-failure.yml index 31f81f979d4..6814c162878 100644 --- a/.github/workflows/reusable-open-issue-on-failure.yml +++ b/.github/workflows/reusable-open-issue-on-failure.yml @@ -1,4 +1,4 @@ -name: Reusable - Open issue on failure +name: Reusable - Open issue on workflow failure on: workflow_call: @@ -11,7 +11,7 @@ jobs: - name: Open issue env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh issue create --title "$GITHUB_WORKFLOW #$GITHUB_RUN_NUMBER failed" \ --label bug \ From 44975c2853eaa122d9cd6f9cef560d1696193211 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 13:11:45 -0800 Subject: [PATCH 6/9] Bump spotless-plugin-gradle from 6.11.0 to 6.12.0 (#4987) Bumps [spotless-plugin-gradle](https://github.com/diffplug/spotless) from 6.11.0 to 6.12.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/gradle/6.11.0...gradle/6.12.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-plugin-gradle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 4a483ed5f35..517ec938c58 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,7 +14,7 @@ repositories { dependencies { implementation("com.google.auto.value:auto-value-annotations:1.10.1") // When updating, update above in plugins too - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.11.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.12.0") // Needed for japicmp but not automatically brought in for some reason. implementation("com.google.guava:guava:31.1-jre") implementation("com.squareup:javapoet:1.13.0") From c2947bf0468e3c3258ea4770f0c76c88e75624ad Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Sat, 26 Nov 2022 09:10:35 -0600 Subject: [PATCH 7/9] Add toString implementation to various log SDK components (#4979) --- .../io/opentelemetry/sdk/OpenTelemetrySdk.java | 4 +++- .../opentelemetry/sdk/OpenTelemetrySdkTest.java | 17 +++++++++++++++++ .../sdk/logs/SdkLoggerProvider.java | 14 ++++++++++++++ .../logs/export/BatchLogRecordProcessor.java | 14 ++++++++++++++ .../sdk/logs/export/MultiLogRecordExporter.java | 13 +++++++++++-- .../logs/export/SimpleLogRecordProcessor.java | 5 +++++ .../sdk/logs/SdkLoggerProviderTest.java | 13 +++++++++++++ .../export/BatchLogRecordProcessorTest.java | 8 ++++++++ .../logs/export/MultiLogRecordExporterTest.java | 9 +++++++++ .../export/SimpleLogRecordProcessorTest.java | 7 +++++++ 10 files changed, 101 insertions(+), 3 deletions(-) diff --git a/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java b/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java index 78263217384..79c264759d4 100644 --- a/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java +++ b/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java @@ -80,12 +80,14 @@ public ContextPropagators getPropagators() { @Override public String toString() { - // TODO(anuraaga): Add logs / propagators + // TODO(anuraaga): Add propagators return "OpenTelemetrySdk{" + "tracerProvider=" + tracerProvider.unobfuscate() + ", meterProvider=" + meterProvider.unobfuscate() + + ", loggerProvider=" + + loggerProvider + "}"; } diff --git a/sdk/all/src/test/java/io/opentelemetry/sdk/OpenTelemetrySdkTest.java b/sdk/all/src/test/java/io/opentelemetry/sdk/OpenTelemetrySdkTest.java index a65080bb6c7..3a9228d9c8c 100644 --- a/sdk/all/src/test/java/io/opentelemetry/sdk/OpenTelemetrySdkTest.java +++ b/sdk/all/src/test/java/io/opentelemetry/sdk/OpenTelemetrySdkTest.java @@ -19,6 +19,8 @@ import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.metrics.Aggregation; import io.opentelemetry.sdk.metrics.InstrumentSelector; import io.opentelemetry.sdk.metrics.InstrumentType; @@ -322,6 +324,8 @@ void stringRepresentation() { when(spanExporter.toString()).thenReturn("MockSpanExporter{}"); when(metricExporter.getDefaultAggregation(any())).thenCallRealMethod(); when(metricExporter.toString()).thenReturn("MockMetricExporter{}"); + LogRecordExporter logRecordExporter = mock(LogRecordExporter.class); + when(logRecordExporter.toString()).thenReturn("MockLogRecordExporter{}"); Resource resource = Resource.builder().put(AttributeKey.stringKey("service.name"), "otel-test").build(); OpenTelemetrySdk sdk = @@ -341,6 +345,13 @@ void stringRepresentation() { InstrumentSelector.builder().setName("instrument").build(), View.builder().setName("new-instrument").build()) .build()) + .setLoggerProvider( + SdkLoggerProvider.builder() + .setResource(resource) + .addLogRecordProcessor( + SimpleLogRecordProcessor.create( + LogRecordExporter.composite(logRecordExporter, logRecordExporter))) + .build()) .build(); assertThat(sdk.toString()) @@ -359,6 +370,12 @@ void stringRepresentation() { + "resource=Resource{schemaUrl=null, attributes={service.name=\"otel-test\"}}, " + "metricReaders=[PeriodicMetricReader{exporter=MockMetricExporter{}, intervalNanos=60000000000}], " + "views=[RegisteredView{instrumentSelector=InstrumentSelector{instrumentName=instrument}, view=View{name=new-instrument, aggregation=DefaultAggregation, attributesProcessor=NoopAttributesProcessor{}}}]" + + "}, " + + "loggerProvider=SdkLoggerProvider{" + + "clock=SystemClock{}, " + + "resource=Resource{schemaUrl=null, attributes={service.name=\"otel-test\"}}, " + + "logLimits=LogLimits{maxNumberOfAttributes=128, maxAttributeValueLength=2147483647}, " + + "logRecordProcessor=SimpleLogRecordProcessor{logRecordExporter=MultiLogRecordExporter{logRecordExporters=[MockLogRecordExporter{}, MockLogRecordExporter{}]}}" + "}" + "}"); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java index 478700742d6..d7b35c9ed86 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java @@ -117,4 +117,18 @@ public CompletableResultCode shutdown() { public void close() { shutdown().join(10, TimeUnit.SECONDS); } + + @Override + public String toString() { + return "SdkLoggerProvider{" + + "clock=" + + sharedState.getClock() + + ", resource=" + + sharedState.getResource() + + ", logLimits=" + + sharedState.getLogLimits() + + ", logRecordProcessor=" + + sharedState.getLogRecordProcessor() + + '}'; + } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java index f327b3b4acc..01b5effc7fa 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java @@ -107,6 +107,20 @@ ArrayList getBatch() { return worker.batch; } + @Override + public String toString() { + return "BatchLogRecordProcessor{" + + "logRecordExporter=" + + worker.logRecordExporter + + ", scheduleDelayNanos=" + + worker.scheduleDelayNanos + + ", maxExportBatchSize=" + + worker.maxExportBatchSize + + ", exporterTimeoutNanos=" + + worker.exporterTimeoutNanos + + '}'; + } + // Worker is a thread that batches multiple logs and calls the registered LogRecordExporter to // export // the data. diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java index f7676d7580c..33d1a1b726a 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java @@ -8,6 +8,7 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.data.LogRecordData; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.logging.Level; @@ -24,6 +25,10 @@ final class MultiLogRecordExporter implements LogRecordExporter { private final LogRecordExporter[] logRecordExporters; + private MultiLogRecordExporter(LogRecordExporter[] logRecordExporters) { + this.logRecordExporters = logRecordExporters; + } + /** * Constructs and returns an instance of this class. * @@ -93,7 +98,11 @@ public CompletableResultCode shutdown() { return CompletableResultCode.ofAll(results); } - private MultiLogRecordExporter(LogRecordExporter[] logRecordExporters) { - this.logRecordExporters = logRecordExporters; + @Override + public String toString() { + return "MultiLogRecordExporter{" + + "logRecordExporters=" + + Arrays.toString(logRecordExporters) + + '}'; } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java index 3bb510718aa..bb891e28435 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java @@ -104,4 +104,9 @@ public CompletableResultCode shutdown() { public CompletableResultCode forceFlush() { return CompletableResultCode.ofAll(pendingExports); } + + @Override + public String toString() { + return "SimpleLogRecordProcessor{" + "logRecordExporter=" + logRecordExporter + '}'; + } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java index 7408fdfc8dc..b663d70de59 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java @@ -346,4 +346,17 @@ void canSetClock() { assertThat(seenLogs.size()).isEqualTo(1); assertThat(seenLogs.get(0).toLogRecordData().getEpochNanos()).isEqualTo(now); } + + @Test + void toString_Valid() { + when(logRecordProcessor.toString()).thenReturn("MockLogRecordProcessor"); + assertThat(sdkLoggerProvider.toString()) + .isEqualTo( + "SdkLoggerProvider{" + + "clock=SystemClock{}, " + + "resource=Resource{schemaUrl=null, attributes={service.name=\"unknown_service:java\", telemetry.sdk.language=\"java\", telemetry.sdk.name=\"opentelemetry\", telemetry.sdk.version=\"1.21.0-SNAPSHOT\"}}, " + + "logLimits=LogLimits{maxNumberOfAttributes=128, maxAttributeValueLength=2147483647}, " + + "logRecordProcessor=MockLogRecordProcessor" + + "}"); + } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java index 1039b7e34bc..cf20eead2d5 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java @@ -420,6 +420,14 @@ void shutdownPropagatesFailure() { assertThat(result.isSuccess()).isFalse(); } + @Test + void toString_Valid() { + when(mockLogRecordExporter.toString()).thenReturn("MockLogRecordExporter"); + assertThat(BatchLogRecordProcessor.builder(mockLogRecordExporter).build().toString()) + .isEqualTo( + "BatchLogRecordProcessor{logRecordExporter=MockLogRecordExporter, scheduleDelayNanos=200000000, maxExportBatchSize=512, exporterTimeoutNanos=30000000000}"); + } + private static final class BlockingLogRecordExporter implements LogRecordExporter { final Object monitor = new Object(); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporterTest.java index 1f970d6bf40..2f781e4e68b 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporterTest.java @@ -136,4 +136,13 @@ void twoLogRecordExporter_FirstThrows() { verify(logRecordExporter1).shutdown(); verify(logRecordExporter2).shutdown(); } + + @Test + void toString_Valid() { + when(logRecordExporter1.toString()).thenReturn("LogRecordExporter1"); + when(logRecordExporter2.toString()).thenReturn("LogRecordExporter2"); + assertThat(LogRecordExporter.composite(logRecordExporter1, logRecordExporter2).toString()) + .isEqualTo( + "MultiLogRecordExporter{logRecordExporters=[LogRecordExporter1, LogRecordExporter2]}"); + } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java index 1550c68b3ef..bace5bdbaf6 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java @@ -119,4 +119,11 @@ void shutdown() { assertThat(shutdown.isSuccess()).isTrue(); verify(logRecordExporter).shutdown(); } + + @Test + void toString_Valid() { + when(logRecordExporter.toString()).thenReturn("MockLogRecordExporter"); + assertThat(logRecordProcessor.toString()) + .isEqualTo("SimpleLogRecordProcessor{logRecordExporter=MockLogRecordExporter}"); + } } From ee2d981bdcc82780b3505cb7b051abe0456ad1ae Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Sat, 26 Nov 2022 09:16:59 -0600 Subject: [PATCH 8/9] Remove support for otel.experimental.sdk.enabled (#4973) --- sdk-extensions/autoconfigure/README.md | 6 +-- ...AutoConfiguredOpenTelemetrySdkBuilder.java | 4 +- .../AutoConfiguredOpenTelemetrySdkTest.java | 51 ------------------- 3 files changed, 4 insertions(+), 57 deletions(-) diff --git a/sdk-extensions/autoconfigure/README.md b/sdk-extensions/autoconfigure/README.md index 49fa7fd350d..4ade5ab7bdf 100644 --- a/sdk-extensions/autoconfigure/README.md +++ b/sdk-extensions/autoconfigure/README.md @@ -44,9 +44,9 @@ for more details. The OpenTelemetry SDK can be disabled entirely. If disabled, `AutoConfiguredOpenTelemetrySdk#getOpenTelemetrySdk()` will return a minimally configured instance (i.e. `OpenTelemetrySdk.builder().build()`). -| System property | Environment variable | Purpose | -|-------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| otel.sdk.disabled | OTEL_SDK_DISABLED | If `true`, disable the OpenTelemetry SDK. Defaults to `false`. The now legacy property `otel.experimental.sdk.enabled` will continue to work with default `true` during a transition period. | +| System property | Environment variable | Purpose | +|-------------------|----------------------|----------------------------------------------------------------| +| otel.sdk.disabled | OTEL_SDK_DISABLED | If `true`, disable the OpenTelemetry SDK. Defaults to `false`. | ## Exporters diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java index 89aaf480f7b..c8d633a4b8f 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java @@ -331,9 +331,7 @@ public AutoConfiguredOpenTelemetrySdk build() { ResourceConfiguration.configureResource(config, serviceClassLoader, resourceCustomizer); OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder().build(); - boolean sdkEnabled = - !config.getBoolean( - "otel.sdk.disabled", !config.getBoolean("otel.experimental.sdk.enabled", true)); + boolean sdkEnabled = !config.getBoolean("otel.sdk.disabled", false); if (sdkEnabled) { SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder(); diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java index fd2daacefef..7ba3a8c1493 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java @@ -359,31 +359,6 @@ private static Supplier> disableExportPropertySupplier() { return () -> props; } - @Test - void disableSdkLegacyProperty() { - BiFunction - traceCustomizer = getTracerProviderBuilderSpy(); - BiFunction - metricCustomizer = getMeterProviderBuilderSpy(); - BiFunction logCustomizer = - getLoggerProviderBuilderSpy(); - - AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = - AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier(() -> singletonMap("otel.experimental.sdk.enabled", "false")) - .addTracerProviderCustomizer(traceCustomizer) - .addMeterProviderCustomizer(metricCustomizer) - .addLoggerProviderCustomizer(logCustomizer) - .build(); - - assertThat(autoConfiguredSdk.getOpenTelemetrySdk()).isInstanceOf(OpenTelemetrySdk.class); - - // When the SDK is disabled, configuration is skipped and none of the customizers are called - verify(traceCustomizer, never()).apply(any(), any()); - verify(metricCustomizer, never()).apply(any(), any()); - verify(logCustomizer, never()).apply(any(), any()); - } - @Test void disableSdk() { BiFunction @@ -409,32 +384,6 @@ void disableSdk() { verify(logCustomizer, never()).apply(any(), any()); } - @Test - void disableSdkNewPropertyWins() { - BiFunction - traceCustomizer = getTracerProviderBuilderSpy(); - BiFunction - metricCustomizer = getMeterProviderBuilderSpy(); - BiFunction logCustomizer = - getLoggerProviderBuilderSpy(); - - AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = - AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier(() -> singletonMap("otel.sdk.disabled", "true")) - .addPropertiesSupplier(() -> singletonMap("otel.experimental.sdk.enabled", "true")) - .addTracerProviderCustomizer(traceCustomizer) - .addMeterProviderCustomizer(metricCustomizer) - .addLoggerProviderCustomizer(logCustomizer) - .build(); - - assertThat(autoConfiguredSdk.getOpenTelemetrySdk()).isInstanceOf(OpenTelemetrySdk.class); - - // When the SDK is disabled, configuration is skipped and none of the customizers are called - verify(traceCustomizer, never()).apply(any(), any()); - verify(metricCustomizer, never()).apply(any(), any()); - verify(logCustomizer, never()).apply(any(), any()); - } - @Test void tracerProviderCustomizer() { InMemorySpanExporter spanExporter = InMemorySpanExporter.create(); From cbd629c579ee0f319479b29e233ccd6a257281b7 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 28 Nov 2022 10:14:44 -0600 Subject: [PATCH 9/9] Implement logging exporter providers (#4950) --- exporters/logging/build.gradle.kts | 2 ++ .../LoggingLogRecordExporterProvider.java | 29 +++++++++++++++++++ .../LoggingMetricExporterProvider.java | 29 +++++++++++++++++++ .../internal/LoggingSpanExporterProvider.java | 29 +++++++++++++++++++ ...logs.ConfigurableLogRecordExporterProvider | 1 + ...metrics.ConfigurableMetricExporterProvider | 1 + ...pi.traces.ConfigurableSpanExporterProvider | 1 + sdk-extensions/autoconfigure/build.gradle.kts | 1 - .../LogRecordExporterConfiguration.java | 22 +++++++++----- .../MetricExporterConfiguration.java | 29 +++++++++++-------- .../SpanExporterConfiguration.java | 23 ++++++++++----- .../sdk/autoconfigure/NotOnClasspathTest.java | 12 ++++---- 12 files changed, 146 insertions(+), 33 deletions(-) create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider diff --git a/exporters/logging/build.gradle.kts b/exporters/logging/build.gradle.kts index 8107ed13a9a..ca1adf08d1a 100644 --- a/exporters/logging/build.gradle.kts +++ b/exporters/logging/build.gradle.kts @@ -13,6 +13,8 @@ dependencies { api(project(":sdk:metrics")) api(project(":sdk:logs")) + implementation(project(":sdk-extensions:autoconfigure-spi")) + testImplementation(project(":sdk:testing")) testImplementation(project(":sdk:logs-testing")) } diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java new file mode 100644 index 00000000000..e6fbd6fbc8d --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; + +/** + * {@link LogRecordExporter} SPI implementation for {@link SystemOutLogRecordExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider { + @Override + public LogRecordExporter createExporter(ConfigProperties config) { + return SystemOutLogRecordExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java new file mode 100644 index 00000000000..47605ac1154 --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.LoggingMetricExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider; +import io.opentelemetry.sdk.metrics.export.MetricExporter; + +/** + * {@link MetricExporter} SPI implementation for {@link LoggingMetricExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingMetricExporterProvider implements ConfigurableMetricExporterProvider { + @Override + public MetricExporter createExporter(ConfigProperties config) { + return LoggingMetricExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java new file mode 100644 index 00000000000..5854a12fe64 --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; +import io.opentelemetry.sdk.trace.export.SpanExporter; + +/** + * {@link SpanExporter} SPI implementation for {@link LoggingSpanExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingSpanExporterProvider implements ConfigurableSpanExporterProvider { + @Override + public SpanExporter createExporter(ConfigProperties config) { + return LoggingSpanExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider new file mode 100644 index 00000000000..8d8842825ba --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingLogRecordExporterProvider diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider new file mode 100644 index 00000000000..3ad21a55ccd --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingMetricExporterProvider diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider new file mode 100644 index 00000000000..8806e4b9608 --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingSpanExporterProvider diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index 182e6389c92..6328e6785c4 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -16,7 +16,6 @@ dependencies { implementation(project(":exporters:common")) compileOnly(project(":exporters:jaeger")) - compileOnly(project(":exporters:logging")) compileOnly(project(":exporters:otlp:all")) compileOnly(project(":exporters:otlp:logs")) compileOnly(project(":exporters:otlp:common")) diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java index 927b4eceb2f..9dd3dc19647 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java @@ -11,7 +11,6 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.exporter.internal.retry.RetryUtil; -import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; @@ -30,6 +29,12 @@ class LogRecordExporterConfiguration { private static final String EXPORTER_NONE = "none"; + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } // Visible for test static Map configureLogRecordExporters( @@ -85,15 +90,18 @@ static LogRecordExporter configureExporter( switch (name) { case "otlp": return configureOtlpLogs(config, meterProvider); - case "logging": - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.SystemOutLogRecordExporter", - "Logging Log Exporter", - "opentelemetry-exporter-logging"); - return SystemOutLogRecordExporter.create(); default: LogRecordExporter spiExporter = spiExportersManager.getByName(name); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.logs.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.logs.exporter: " + name); } return spiExporter; diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java index ac8e6784b3f..75671f8d314 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java @@ -10,7 +10,6 @@ import static io.opentelemetry.sdk.autoconfigure.OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF; import io.opentelemetry.exporter.internal.retry.RetryUtil; -import io.opentelemetry.exporter.logging.LoggingMetricExporter; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; @@ -24,12 +23,20 @@ import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import java.util.function.BiFunction; import javax.annotation.Nullable; final class MetricExporterConfiguration { private static final Duration DEFAULT_EXPORT_INTERVAL = Duration.ofMinutes(1); + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } static MetricReader configureExporter( String name, @@ -46,12 +53,18 @@ static MetricReader configureExporter( case "otlp": metricExporter = configureOtlpMetrics(config); break; - case "logging": - metricExporter = configureLoggingExporter(); - break; default: MetricExporter spiExporter = configureSpiExporter(name, config, serviceClassLoader); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.metrics.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.metrics.exporter: " + name); } metricExporter = spiExporter; @@ -61,14 +74,6 @@ static MetricReader configureExporter( return configurePeriodicMetricReader(config, metricExporter); } - private static MetricExporter configureLoggingExporter() { - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.LoggingMetricExporter", - "Logging Metrics Exporter", - "opentelemetry-exporter-logging"); - return LoggingMetricExporter.create(); - } - // Visible for testing. @Nullable static MetricExporter configureSpiExporter( diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java index a3d2c394783..89a42620b48 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java @@ -14,7 +14,6 @@ import io.opentelemetry.exporter.internal.retry.RetryUtil; import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter; import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporterBuilder; -import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; @@ -27,6 +26,7 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import java.time.Duration; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -35,6 +35,12 @@ final class SpanExporterConfiguration { private static final String EXPORTER_NONE = "none"; + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } // Visible for testing static Map configureSpanExporters( @@ -92,15 +98,18 @@ static SpanExporter configureExporter( return configureJaeger(config, meterProvider); case "zipkin": return configureZipkin(config); - case "logging": - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.LoggingSpanExporter", - "Logging Trace Exporter", - "opentelemetry-exporter-logging"); - return LoggingSpanExporter.create(); default: SpanExporter spiExporter = spiExportersManager.getByName(name); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.traces.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.traces.exporter: " + name); } return spiExporter; diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java index a4a476b2c62..f3c36438fd0 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java @@ -77,8 +77,8 @@ void loggingSpans() { "logging", EMPTY, NamedSpiManager.createEmpty(), MeterProvider.noop())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Trace Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.traces.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test @@ -92,8 +92,8 @@ void loggingMetrics() { (a, unused) -> a)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Metrics Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.metrics.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test @@ -104,8 +104,8 @@ void loggingLogs() { "logging", EMPTY, NamedSpiManager.createEmpty(), MeterProvider.noop())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Log Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.logs.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test