From bda6cb0fec5dcebbc271e2bb1e1f43bed93eef8f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:16:57 +0000 Subject: [PATCH 001/108] Configure Renovate (#966) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..39a2b6e9a --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} From 8ac65277527af331828556f518f6f820150e294e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:20:24 +0000 Subject: [PATCH 002/108] Update autovalueVersion to v1.10.2 (#967) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index abfb000eb..2be29ccc9 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -15,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -val autovalueVersion = "1.10.1" +val autovalueVersion = "1.10.2" dependencies { api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-exporter-otlp-common") From 8e4b2caca3663b96898caf9de198b1624bf32949 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 21 Jul 2023 14:06:56 -0700 Subject: [PATCH 003/108] Renovate config updates (#976) --- .github/renovate.json5 | 38 ++++++++++++++++++++++++++++++++++++++ renovate.json | 6 ------ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 .github/renovate.json5 delete mode 100644 renovate.json diff --git a/.github/renovate.json5 b/.github/renovate.json5 new file mode 100644 index 000000000..aa1e9d48f --- /dev/null +++ b/.github/renovate.json5 @@ -0,0 +1,38 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ], + "packageRules": [ + { + // junit-pioneer 2+ requires Java 11+ + "matchPackageNames": ["org.junit-pioneer:junit-pioneer"], + "matchUpdateTypes": ["major"], + "enabled": false + }, + { + // mockito 5+ requires Java 11+ + "matchPackagePrefixes": ["org.mockito:"], + "matchUpdateTypes": ["major"], + "enabled": false + }, + { + // pinned version for compatibility + "matchPackageNames": ["io.micrometer:micrometer-core"], + "matchCurrentVersion": "1.1.0", + "enabled": false + }, + { + // pinned version for compatibility + "matchPackageNames": ["io.micrometer:micrometer-core"], + "matchCurrentVersion": "1.1.0", + "enabled": false + }, + { + // pinned version for compatibility + "matchPackagePrefixes": ["org.apache.maven:"], + "matchCurrentVersion": "3.5.0", + "enabled": false + } + ] +} diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 39a2b6e9a..000000000 --- a/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:base" - ] -} From 99201134f650b60926d5e626f04bb5b02c579cec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:09:33 -0700 Subject: [PATCH 004/108] Update gradle/wrapper-validation-action action to v1.1.0 (#977) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 18082e551..75f8f8d35 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: gradle/wrapper-validation-action@v1.0.6 + - uses: gradle/wrapper-validation-action@v1.1.0 From 8d8ab736bf8ae81d41d33e327c71a0108c9068b3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:09:53 -0700 Subject: [PATCH 005/108] Update dependency io.micrometer:micrometer-core to v1.11.2 (#970) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index 17e63a005..e6b136f32 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.9.5") + testImplementation("io.micrometer:micrometer-core:1.11.2") } testing { From eb5d1771ec064f138c592a15e3941e4fb2a883c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:17:16 -0700 Subject: [PATCH 006/108] Update dependency org.junit:junit-bom to v5.10.0 (#979) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index ebf01b2f6..e83de82a4 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -15,7 +15,7 @@ val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", "com.google.guava:guava-bom:32.1.1-jre", "com.linecorp.armeria:armeria-bom:1.24.2", - "org.junit:junit-bom:5.9.3", + "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.56.1", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", "org.testcontainers:testcontainers-bom:1.18.3" From 38b14d9b210cb8c4be484d5e87b389c6f33cffad Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 16:26:21 -0700 Subject: [PATCH 007/108] Update dependency com.linecorp.armeria:armeria-bom to v1.24.3 (#980) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index e83de82a4..b5d0a3f8d 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -14,7 +14,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", "com.google.guava:guava-bom:32.1.1-jre", - "com.linecorp.armeria:armeria-bom:1.24.2", + "com.linecorp.armeria:armeria-bom:1.24.3", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.56.1", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", From 895d43d8a3f601d2a8c242611d49b7a80d6e895f Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 26 Jul 2023 07:38:06 -0700 Subject: [PATCH 008/108] Remove dependabot (#978) --- .github/dependabot.yml | 40 ------------------- .../update-gradle-wrappers-daily.yml | 34 ---------------- 2 files changed, 74 deletions(-) delete mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/update-gradle-wrappers-daily.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index f10dcdec7..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 2 -registries: - gradle-plugin-portal: - type: maven-repository - url: https://plugins.gradle.org/m2 - username: dummy # Required by dependabot - password: dummy # Required by dependabot -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - labels: # overriding the default which is to add both "dependencies" and "github_actions" - - "dependencies" - - - package-ecosystem: "gradle" - directory: "/" - ignore: - - dependency-name: "io.micrometer:micrometer-core" - # compileOnly dependency on old micrometer-core version is intentional - versions: [ "(1.1.0,)" ] - - dependency-name: "org.apache.maven:maven-plugin-api" - # static instrumenter maven plugin uses old maven API version for better compatibility - versions: [ "(3.5.0,)" ] - - dependency-name: "org.apache.maven:maven-core" - # compileOnly dependency that matches the maven-plugin-api version in the static instrumenter maven plugin - versions: [ "(3.5.0,)" ] - - dependency-name: "org.junit-pioneer:junit-pioneer" - # junit-pioneer 2.x requires Java 11 - versions: [ "[1,)" ] - - dependency-name: "org.mockito:*" - # mockito 5 requires Java 11 - versions: [ "[5,)" ] - registries: - - gradle-plugin-portal - schedule: - interval: "daily" - labels: # overriding the default which is to add both "dependencies" and "java" - - "dependencies" - open-pull-requests-limit: 10 diff --git a/.github/workflows/update-gradle-wrappers-daily.yml b/.github/workflows/update-gradle-wrappers-daily.yml deleted file mode 100644 index 2e46716ee..000000000 --- a/.github/workflows/update-gradle-wrappers-daily.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Update gradle wrappers (daily) - -on: - schedule: - # daily at 1:30 UTC - - cron: "30 1 * * *" - workflow_dispatch: - -jobs: - update-gradle-wrapper: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - - - name: Update Gradle Wrapper - uses: gradle-update/update-gradle-wrapper-action@v1 - with: - # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows - github-token: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }} - - workflow-notification: - needs: - - update-gradle-wrapper - if: always() - uses: ./.github/workflows/reusable-workflow-notification.yml - with: - success: ${{ needs.update-gradle-wrapper.result == 'success' }} From 9e4de617d79cea1064e2c1f20f1fbdc70966446d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 07:44:27 -0700 Subject: [PATCH 009/108] Update dependency com.gradle.enterprise:com.gradle.enterprise.gradle.plugin to v3.14.1 (#981) Co-authored-by: renovate[bot] <29139614+renovate[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 d760e8066..41b625ec6 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.20.0") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") - implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.14") + implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.14.1") } spotless { From ef14fb0ca7e2974b3218e50daf04f60313ba4e0e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 14:48:46 +0000 Subject: [PATCH 010/108] Update plugin com.gradle.enterprise to v3.14.1 (#982) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 02c580d74..fa53c7376 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,7 @@ pluginManagement { plugins { id("com.github.ben-manes.versions") version "0.47.0" id("com.github.johnrengelman.shadow") version "8.1.1" - id("com.gradle.enterprise") version "3.14" + id("com.gradle.enterprise") version "3.14.1" id("io.github.gradle-nexus.publish-plugin") version "1.3.0" } } From 47f05dee61af2b912489932096dcaea12c054f15 Mon Sep 17 00:00:00 2001 From: Sam DeHaan Date: Wed, 26 Jul 2023 14:17:03 -0400 Subject: [PATCH 011/108] [jmx-metrics] Collect in callback (#949) Co-authored-by: Ryan Fitzpatrick <10867373+rmfitzpatrick@users.noreply.github.com> Co-authored-by: jason plumb <75337021+breedx-splk@users.noreply.github.com> --- jmx-metrics/README.md | 5 + .../integrationTest/resources/script.groovy | 16 +- .../jmxmetrics/GroovyMetricEnvironment.java | 291 +++++++++++++----- .../jmxmetrics/InstrumentHelper.groovy | 227 +++++++++----- .../contrib/jmxmetrics/MBeanHelper.groovy | 27 +- .../contrib/jmxmetrics/OtelHelper.groovy | 82 ++--- .../jmxmetrics/InstrumenterHelperTest.java | 17 +- 7 files changed, 433 insertions(+), 232 deletions(-) diff --git a/jmx-metrics/README.md b/jmx-metrics/README.md index 30e7a7f91..29e2db023 100644 --- a/jmx-metrics/README.md +++ b/jmx-metrics/README.md @@ -128,6 +128,11 @@ mutually exclusive with `otel.jmx.groovy.script`. The currently supported target [`CompositeData`](https://docs.oracle.com/javase/7/docs/api/javax/management/openmbean/CompositeData.html) instances, each key of their `CompositeType` `keySet` will be `.`-appended to the specified `instrumentName`, whose resulting instrument will be updated for each respective value. + - If the underlying MBean(s) held by the provided MBeanHelper are a mixed set of + [`CompositeData`](https://docs.oracle.com/javase/7/docs/api/javax/management/openmbean/CompositeData.html) instances + and simple values, the InstrumentHelper will not attempt to collect the metric. This is to prevent generating + metrics identified with the `instrumentName` and also the `instrumentName` with the `keySet` `.`-appended, + which breaks OpenTelemetry metric conventions. `otel.instrument()` provides additional signatures to obtain and update the returned `InstrumentHelper`: diff --git a/jmx-metrics/src/integrationTest/resources/script.groovy b/jmx-metrics/src/integrationTest/resources/script.groovy index 0592ad3e5..0ed6c493f 100644 --- a/jmx-metrics/src/integrationTest/resources/script.groovy +++ b/jmx-metrics/src/integrationTest/resources/script.groovy @@ -17,11 +17,13 @@ import io.opentelemetry.api.common.Attributes def loadMatches = otel.queryJmx("org.apache.cassandra.metrics:type=Storage,name=Load") -def load = loadMatches.first() +if (!loadMatches.isEmpty()) { + def load = loadMatches.first() -def lvr = otel.longHistogram( - "cassandra.storage.load", - "Size, in bytes, of the on disk data size this node manages", - "By" - ) -lvr.record(load.Count, Attributes.builder().put("myKey", "myVal").build()) + def lvr = otel.longHistogram( + "cassandra.storage.load", + "Size, in bytes, of the on disk data size this node manages", + "By" + ) + lvr.record(load.Count, Attributes.builder().put("myKey", "myVal").build()) +} diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/GroovyMetricEnvironment.java b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/GroovyMetricEnvironment.java index 523599fb9..a34a14ba9 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/GroovyMetricEnvironment.java +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/GroovyMetricEnvironment.java @@ -5,8 +5,11 @@ package io.opentelemetry.contrib.jmxmetrics; +import groovy.lang.Closure; +import groovy.lang.Tuple2; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.metrics.BatchCallback; import io.opentelemetry.api.metrics.DoubleCounter; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.DoubleUpDownCounter; @@ -16,20 +19,25 @@ import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.ObservableDoubleMeasurement; import io.opentelemetry.api.metrics.ObservableLongMeasurement; +import io.opentelemetry.api.metrics.ObservableMeasurement; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.InstrumentValueType; import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.annotation.Nullable; public class GroovyMetricEnvironment { - private final SdkMeterProvider meterProvider; private final Meter meter; @@ -42,6 +50,12 @@ public class GroovyMetricEnvironment { longUpdaterRegistry = new ConcurrentHashMap<>(); private final Map>> doubleUpdaterRegistry = new ConcurrentHashMap<>(); + private final Map>> batchUpdaterRegistry = + new ConcurrentHashMap<>(); + private final Map>> + batchCallbackRegistry = new ConcurrentHashMap<>(); + private final Map instrumentOnceRegistry = + new ConcurrentHashMap<>(); /** * A central context for creating and exporting metrics, to be used by groovy scripts via {@link @@ -218,19 +232,27 @@ public LongHistogram getLongHistogram( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableDoubleMeasurement for the gauge */ - public void registerDoubleValueCallback( + public ObservableDoubleMeasurement registerDoubleValueCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .gaugeBuilder(name) - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedDoubleObserver( - name, description, unit, InstrumentType.OBSERVABLE_GAUGE, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, + description, + unit, + InstrumentType.OBSERVABLE_GAUGE, + InstrumentValueType.DOUBLE) + .hashCode(); + + return registerCallback( + doubleUpdaterRegistry, + () -> meter.gaugeBuilder(name).setDescription(description).setUnit(unit).buildObserver(), + descriptorHash, + updater); } /** @@ -240,19 +262,29 @@ public void registerDoubleValueCallback( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableLongMeasurement for the gauge */ - public void registerLongValueCallback( + public ObservableLongMeasurement registerLongValueCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .gaugeBuilder(name) - .ofLongs() - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedLongObserver(name, description, unit, InstrumentType.OBSERVABLE_GAUGE, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, description, unit, InstrumentType.OBSERVABLE_GAUGE, InstrumentValueType.LONG) + .hashCode(); + + return registerCallback( + longUpdaterRegistry, + () -> + meter + .gaugeBuilder(name) + .ofLongs() + .setDescription(description) + .setUnit(unit) + .buildObserver(), + descriptorHash, + updater); } /** @@ -262,20 +294,33 @@ public void registerLongValueCallback( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableDoubleMeasurement for the counter */ - public void registerDoubleCounterCallback( + public ObservableDoubleMeasurement registerDoubleCounterCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .counterBuilder(name) - .ofDoubles() - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedDoubleObserver( - name, description, unit, InstrumentType.OBSERVABLE_COUNTER, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, + description, + unit, + InstrumentType.OBSERVABLE_COUNTER, + InstrumentValueType.DOUBLE) + .hashCode(); + + return registerCallback( + doubleUpdaterRegistry, + () -> + meter + .counterBuilder(name) + .setDescription(description) + .setUnit(unit) + .ofDoubles() + .buildObserver(), + descriptorHash, + updater); } /** @@ -285,19 +330,27 @@ public void registerDoubleCounterCallback( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableLongMeasurement for the counter */ - public void registerLongCounterCallback( + public ObservableLongMeasurement registerLongCounterCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .counterBuilder(name) - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedLongObserver( - name, description, unit, InstrumentType.OBSERVABLE_COUNTER, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, + description, + unit, + InstrumentType.OBSERVABLE_COUNTER, + InstrumentValueType.LONG) + .hashCode(); + + return registerCallback( + longUpdaterRegistry, + () -> meter.counterBuilder(name).setDescription(description).setUnit(unit).buildObserver(), + descriptorHash, + updater); } /** @@ -307,20 +360,33 @@ public void registerLongCounterCallback( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableDoubleMeasurement for the counter */ - public void registerDoubleUpDownCounterCallback( + public ObservableDoubleMeasurement registerDoubleUpDownCounterCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .upDownCounterBuilder(name) - .ofDoubles() - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedDoubleObserver( - name, description, unit, InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, + description, + unit, + InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, + InstrumentValueType.DOUBLE) + .hashCode(); + + return registerCallback( + doubleUpdaterRegistry, + () -> + meter + .upDownCounterBuilder(name) + .setDescription(description) + .setUnit(unit) + .ofDoubles() + .buildObserver(), + descriptorHash, + updater); } /** @@ -330,56 +396,111 @@ public void registerDoubleUpDownCounterCallback( * @param description metric description * @param unit - metric unit * @param updater - the value updater + * @return the ObservableLongMeasurement for the counter */ - public void registerLongUpDownCounterCallback( + public ObservableLongMeasurement registerLongUpDownCounterCallback( final String name, final String description, final String unit, final Consumer updater) { - meter - .upDownCounterBuilder(name) - .setDescription(description) - .setUnit(unit) - .buildWithCallback( - proxiedLongObserver( - name, description, unit, InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, updater)); + int descriptorHash = + InstrumentDescriptor.create( + name, + description, + unit, + InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, + InstrumentValueType.LONG) + .hashCode(); + + return registerCallback( + longUpdaterRegistry, + () -> + meter + .upDownCounterBuilder(name) + .setDescription(description) + .setUnit(unit) + .buildObserver(), + descriptorHash, + updater); } - private Consumer proxiedDoubleObserver( - final String name, - final String description, - final String unit, - final InstrumentType instrumentType, - final Consumer updater) { - InstrumentDescriptor descriptor = - InstrumentDescriptor.create( - name, description, unit, instrumentType, InstrumentValueType.DOUBLE); - doubleUpdaterRegistry.putIfAbsent(descriptor.hashCode(), new AtomicReference<>()); - AtomicReference> existingUpdater = - doubleUpdaterRegistry.get(descriptor.hashCode()); - existingUpdater.set(updater); - return doubleResult -> { - Consumer existing = existingUpdater.get(); - existing.accept(doubleResult); - }; + private T registerCallback( + final Map>> registry, + final Supplier observerBuilder, + final int descriptorHash, + final Consumer updater) { + + // Only build the instrument if it isn't already in the registry + ObservableMeasurement obs = instrumentOnceRegistry.get(descriptorHash); + if (obs == null) { + T observer = observerBuilder.get(); + instrumentOnceRegistry.put(descriptorHash, observer); + // If an updater was not provided, the measurement is expected to be added + // to a group batchcallback using the registerBatchCallback function + if (updater != null) { + Consumer cb = proxiedObserver(descriptorHash, registry, updater); + meter.batchCallback(() -> cb.accept(observer), observer); + } + return observer; + } else if (updater != null) { + // If the instrument has already been built with the appropriate proxied observer, + // update the registry so that the callback has the appropriate updater function + registry.get(descriptorHash).set(updater); + } + + return (T) obs; } - private Consumer proxiedLongObserver( - final String name, - final String description, - final String unit, - final InstrumentType instrumentType, - final Consumer updater) { - InstrumentDescriptor descriptor = - InstrumentDescriptor.create( - name, description, unit, instrumentType, InstrumentValueType.LONG); - longUpdaterRegistry.putIfAbsent(descriptor.hashCode(), new AtomicReference<>()); - AtomicReference> existingUpdater = - longUpdaterRegistry.get(descriptor.hashCode()); - existingUpdater.set(updater); - return longResult -> { - Consumer existing = existingUpdater.get(); - existing.accept(longResult); - }; + /** + * Register a collection of observables in a single batch callback + * + * @param identifier - object used to identify the callback to have only one callback + * @param callback - closure that records measurements for the observables + * @param measurement - first observable, the SDK expects this is always collected + * @param additional - remaining observable, the SDK expects this is sometimes collected + */ + public void registerBatchCallback( + Object identifier, + Closure callback, + ObservableMeasurement measurement, + ObservableMeasurement... additional) { + int hash = identifier.hashCode(); + // Store the callback in the registry so the proxied callback always runs the latest + // metric collection closure + batchUpdaterRegistry.putIfAbsent(hash, new AtomicReference<>()); + batchUpdaterRegistry.get(hash).set(callback); + + // collect the set of instruments into a set so we can compare to what's previously been + // registered + Set instrumentSet = + Arrays.stream(additional).collect(Collectors.toCollection(HashSet::new)); + instrumentSet.add(measurement); + + Tuple2> existingCallback = + batchCallbackRegistry.get(hash); + // If this is our first attempt to register this callback or the list of relevant instruments + // has changed, we need register the callback. + if (existingCallback == null || !existingCallback.getV2().equals(instrumentSet)) { + // If the callback has already been created, and we're here to update the set of instruments + // make sure we close the previous callback + if (existingCallback != null) { + existingCallback.getV1().close(); + } + batchCallbackRegistry.put( + hash, + new Tuple2<>( + meter.batchCallback( + () -> batchUpdaterRegistry.get(hash).get().call(), measurement, additional), + instrumentSet)); + } + } + + private Consumer proxiedObserver( + final int descriptorHash, + final Map>> registry, + final Consumer updater) { + registry.putIfAbsent(descriptorHash, new AtomicReference<>()); + registry.get(descriptorHash).set(updater); + return result -> registry.get(descriptorHash).get().accept(result); } } diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/InstrumentHelper.groovy b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/InstrumentHelper.groovy index faf0e2bd9..369a4a6b1 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/InstrumentHelper.groovy +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/InstrumentHelper.groovy @@ -7,6 +7,10 @@ package io.opentelemetry.contrib.jmxmetrics import groovy.jmx.GroovyMBean import groovy.transform.PackageScope +import io.opentelemetry.api.metrics.ObservableMeasurement + +import javax.management.AttributeNotFoundException +import javax.management.InvalidAttributeValueException import java.util.logging.Logger import javax.management.openmbean.CompositeData @@ -17,14 +21,13 @@ import javax.management.openmbean.CompositeData * * Intended to be used via the script-bound `otel` {@link OtelHelper} instance methods: * - * def threadCount = otel.instrument(myThreadingMBeanHelper, + * otel.instrument(myThreadingMBeanHelper, * "jvm.threads.count", "number of threads", * "1", [ * "myLabel": { mbean -> mbean.name().getKeyProperty("myObjectNameProperty") }, * "myOtherLabel": { "myLabelValue" } * ], "ThreadCount", otel.&longUpDownCounter) * - * threadCount.update() * * If the underlying MBean(s) held by the MBeanHelper are * {@link CompositeData} instances, each key of their CompositeType's @@ -32,7 +35,7 @@ import javax.management.openmbean.CompositeData * updated for each respective value. */ class InstrumentHelper { - private static final Logger logger = Logger.getLogger(InstrumentHelper.class.getName()); + private static final Logger logger = Logger.getLogger(InstrumentHelper.class.getName()) private final MBeanHelper mBeanHelper private final String instrumentName @@ -41,6 +44,7 @@ class InstrumentHelper { private final Map> mBeanAttributes private final Map labelFuncs private final Closure instrument + private final GroovyMetricEnvironment metricEnvironment /** * An InstrumentHelper provides the ability to easily create and update {@link io.opentelemetry.api.metrics.Instrument} @@ -52,13 +56,15 @@ class InstrumentHelper { * @param description - the resulting instruments' description to register. * @param unit - the resulting instruments' unit to register. * @param labelFuncs - A {@link Map} of label names and values to be determined by custom - * {@link GroovyMBean}-provided Closures: (e.g. [ "myLabelName" : { mbean -> "myLabelValue"} ]). The + * {@link GroovyMBean}-provided Closures: (e.g. [ "myLabelName" : { mbean -> "myLabelValue"} ]). The * resulting Label instances will be used for each individual update. * @param attribute - The {@link GroovyMBean} attribute for which to use as the instrument value. * @param instrument - The {@link io.opentelemetry.api.metrics.Instrument}-producing {@link OtelHelper} method pointer: * (e.g. new OtelHelper().&doubleValueRecorder) + * @param metricenvironment - The {@link GroovyMetricEnvironment} used to register callbacks onto the SDK meter for + * batch callbacks used to handle {@link CompositeData} */ - InstrumentHelper(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, Map> labelFuncs, Map>> MBeanAttributes, Closure instrument) { + InstrumentHelper(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, Map> labelFuncs, Map>> MBeanAttributes, Closure instrument, GroovyMetricEnvironment metricEnvironment) { this.mBeanHelper = mBeanHelper this.instrumentName = instrumentName this.description = description @@ -66,126 +72,185 @@ class InstrumentHelper { this.labelFuncs = labelFuncs this.mBeanAttributes = MBeanAttributes this.instrument = instrument + this.metricEnvironment = metricEnvironment } void update() { - // Tuples of the form (mbean, attribute, value) - def values = mBeanHelper.getAttributes(mBeanAttributes.keySet()) - - // If there are no tuples with non-null value, return early - if (values.find {it.getV3() != null } == null) { - logger.warning("No valid value(s) for ${instrumentName} - ${mBeanHelper}.${mBeanAttributes.keySet().join(",")}") + def mbeans = mBeanHelper.getMBeans() + def compositeAttributes = [] + def simpleAttributes = [] + if (mbeans.size() == 0) { return } - // Observer instruments need to have a single updater set at build time, so pool all - // update operations in a list of closures per instrument to be executed after all values - // are established, potentially as a single updater. This is done because a single MBeanHelper - // can represent multiple MBeans (each with different values for an attribute) and the labelFuncs - // will create multiple datapoints from the same instrument identifiers. - def tupleToUpdates = [:] // tuple is of form (instrument, instrumentName, description, unit) - - values.each { collectedValue -> - def mbean = collectedValue.getV1() - def attribute = collectedValue.getV2() - def value = collectedValue.getV3() - if (value instanceof CompositeData) { - value.getCompositeType().keySet().each { key -> - def val = value.get(key) - def updatedInstrumentName = "${instrumentName}.${key}" - def labels = getLabels(mbean, labelFuncs, mBeanAttributes[attribute]) - def tuple = new Tuple(instrument, updatedInstrumentName, description, unit) - logger.fine("Recording ${updatedInstrumentName} - ${instrument.method} w/ ${val} - ${labels}") - if (!tupleToUpdates.containsKey(tuple)) { - tupleToUpdates[tuple] = [] - } - tupleToUpdates[tuple].add(prepareUpdateClosure(instrument, val, labels)) + mBeanAttributes.keySet().each { attribute -> + try { + // Look at the collected mbeans to evaluate if the attributes requested are + // composite data types or simple. Composite types require different parsing to + // end up with multiple recorders in the same callback. + def keySet = getCompositeKeys(attribute, mbeans) + if (keySet.size() > 0) { + compositeAttributes.add(new Tuple2>(attribute, keySet)) + } else { + simpleAttributes.add(attribute) } - } else if (value != null) { - def labels = getLabels(mbean, labelFuncs, mBeanAttributes[attribute]) - def tuple = new Tuple(instrument, instrumentName, description, unit) - logger.fine("Recording ${instrumentName} - ${instrument.method} w/ ${value} - ${labels}") - if (!tupleToUpdates.containsKey(tuple)) { - tupleToUpdates[tuple] = [] - } - tupleToUpdates[tuple].add(prepareUpdateClosure(instrument, value, labels)) + } catch (AttributeNotFoundException ignored) { + logger.fine("Attribute ${attribute} not found on any of the collected mbeans") + } catch (InvalidAttributeValueException ignored) { + logger.info("Attribute ${attribute} was not consistently CompositeData for " + + "collected mbeans. The metrics gatherer cannot collect measurements for an instrument " + + "when the mbeans attribute values are not all CompositeData or all simple values.") } } - tupleToUpdates.each {tuple, updateClosures -> - def instrument = tuple.getAt(0) - def instrumentName = tuple.getAt(1) - def description = tuple.getAt(2) - def unit = tuple.getAt(3) - + if (simpleAttributes.size() > 0) { + def simpleUpdateClosure = prepareUpdateClosure(mbeans, simpleAttributes) if (instrumentIsDoubleObserver(instrument) || instrumentIsLongObserver(instrument)) { - // Though the instrument updater is only set at build time, - // our GroovyMetricEnvironment helpers ensure the updater - // uses the Closure specified here. instrument(instrumentName, description, unit, { result -> - updateClosures.each { update -> - update(result) - } + simpleUpdateClosure(result) }) } else { - def inst = instrument(instrumentName, description, unit) - updateClosures.each { - it(inst) + simpleUpdateClosure(instrument(instrumentName, description, unit)) + } + } + + if (compositeAttributes.size() > 0) { + registerCompositeUpdateClosures(mbeans, compositeAttributes) + } + } + + // This function retrieves the set of CompositeData keys for the given attribute for the currently + // collected mbeans. If the attribute is all simple values it will return an empty list. + // If the attribute is inconsistent across mbeans, it will throw an exception. + private static Set getCompositeKeys(String attribute, List beans) throws AttributeNotFoundException, InvalidAttributeValueException { + def isComposite = false + def isFound = false + def keySet = beans.collect { bean -> + try { + def value = MBeanHelper.getBeanAttribute(bean, attribute) + if (value == null) { + // Null represents an attribute not found exception in MBeanHelper + [] + } else if (value instanceof CompositeData) { + // If we've found a simple attribute, throw an exception as this attribute + // was mixed between simple & composite + if (!isComposite && isFound) { + throw new InvalidAttributeValueException() + } + isComposite = true + isFound = true + value.getCompositeType().keySet() + } else { + // If we've previously found a composite attribute, throw an exception as this attribute + // was mixed between simple & composite + if (isComposite) { + throw new InvalidAttributeValueException() + } + isFound = true + [] } + } catch (AttributeNotFoundException | NullPointerException ignored) { + [] } + }.flatten() + .toSet() + + if (!isFound) { + throw new AttributeNotFoundException() } + + return keySet } private static Map getLabels(GroovyMBean mbean, Map labelFuncs, Map additionalLabels) { def labels = [:] labelFuncs.each { label, labelFunc -> - labels[label] = labelFunc(mbean) as String + labels[label] = labelFunc(mbean) as String } - additionalLabels.each {label, labelFunc -> + additionalLabels.each { label, labelFunc -> labels[label] = labelFunc(mbean) as String } return labels } - private static Closure prepareUpdateClosure(inst, value, labels) { - def labelMap = GroovyMetricEnvironment.mapToAttributes(labels) - if (instrumentIsLongObserver(inst)) { - return { result -> - result.record((long) value, labelMap) + // Create a closure for simple attributes that will retrieve mbean information on + // callback to ensure that metrics are collected on request + private Closure prepareUpdateClosure(List mbeans, attributes) { + return { result -> + [mbeans, attributes].combinations().each { pair -> + def (mbean, attribute) = pair + def value = MBeanHelper.getBeanAttribute(mbean, attribute) + if (value != null) { + def labels = getLabels(mbean, labelFuncs, mBeanAttributes[attribute]) + logger.fine("Recording ${instrumentName} - ${instrument.method} w/ ${value} - ${labels}") + recordDataPoint(instrument, result, value, GroovyMetricEnvironment.mapToAttributes(labels)) + } } + } + } + + // Create a closure for composite data attributes that will retrieve mbean information + // on callback to ensure that metrics are collected on request. This will create a single + // batch callback for all of the metrics collected on a single attribute. + private void registerCompositeUpdateClosures(List mbeans, attributes) { + attributes.each { pair -> + def (attribute, keys) = pair + def instruments = keys.collect { new Tuple2(it, instrument("${instrumentName}.${it}", description, unit, null)) } + + metricEnvironment.registerBatchCallback("${instrumentName}.${attribute}", () -> { + mbeans.each { mbean -> + def value = MBeanHelper.getBeanAttribute(mbean, attribute) + if (value != null && value instanceof CompositeData) { + instruments.each { inst -> + def val = value.get(inst.v1) + def labels = getLabels(mbean, labelFuncs, mBeanAttributes[attribute]) + logger.fine("Recording ${"${instrumentName}.${inst.v1}"} - ${instrument.method} w/ ${val} - ${labels}") + recordDataPoint(instrument, inst.v2, val, GroovyMetricEnvironment.mapToAttributes(labels)) + } + } + } + }, instruments.first().v2, *instruments.tail().collect { it.v2 }) + } + } + + // Based on the type of instrument, record the data point in the way expected by the observable + private static void recordDataPoint(inst, result, value, labelMap) { + if (instrumentIsLongObserver(inst)) { + result.record((long) value, labelMap) } else if (instrumentIsDoubleObserver(inst)) { - return { result -> - result.record((double) value, labelMap) - } + result.record((double) value, labelMap) } else if (instrumentIsCounter(inst)) { - return { i -> i.add(value, labelMap) } + result.add(value, labelMap) } else { - return { i -> i.record(value, labelMap) } + result.record(value, labelMap) } } - @PackageScope static boolean instrumentIsDoubleObserver(inst) { + @PackageScope + static boolean instrumentIsDoubleObserver(inst) { return [ - "doubleCounterCallback", - "doubleUpDownCounterCallback", - "doubleValueCallback", + "doubleCounterCallback", + "doubleUpDownCounterCallback", + "doubleValueCallback", ].contains(inst.method) } - @PackageScope static boolean instrumentIsLongObserver(inst) { + @PackageScope + static boolean instrumentIsLongObserver(inst) { return [ - "longCounterCallback", - "longUpDownCounterCallback", - "longValueCallback", + "longCounterCallback", + "longUpDownCounterCallback", + "longValueCallback", ].contains(inst.method) } - @PackageScope static boolean instrumentIsCounter(inst) { + @PackageScope + static boolean instrumentIsCounter(inst) { return [ - "doubleCounter", - "doubleUpDownCounter", - "longCounter", - "longUpDownCounter" + "doubleCounter", + "doubleUpDownCounter", + "longCounter", + "longUpDownCounter" ].contains(inst.method) } } diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy index 42fa92eca..1ba98467e 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy @@ -74,11 +74,11 @@ class MBeanHelper { } @PackageScope List getMBeans() { - if (mbeans == null) { + if (mbeans == null || mbeans.size() == 0) { logger.warning("No active MBeans. Be sure to fetch() before updating any applicable instruments.") return [] } - return mbeans + return isSingle ? [mbeans[0]]: mbeans } @PackageScope List getAttribute(String attribute) { @@ -88,12 +88,7 @@ class MBeanHelper { def ofInterest = isSingle ? [mbeans[0]]: mbeans return ofInterest.collect { - try { - it.getProperty(attribute) - } catch (AttributeNotFoundException e) { - logger.warning("Expected attribute ${attribute} not found in mbean ${it.name()}") - null - } + getBeanAttribute(it, attribute) } } @@ -105,12 +100,16 @@ class MBeanHelper { def ofInterest = isSingle ? [mbeans[0]]: mbeans return [ofInterest, attributes].combinations().collect { pair -> def (bean, attribute) = pair - try { - new Tuple3(bean, attribute, bean.getProperty(attribute)) - } catch (AttributeNotFoundException e) { - logger.info("Expected attribute ${attribute} not found in mbean ${bean.name()}") - new Tuple3(bean, attribute, null) - } + new Tuple3(bean, attribute, getBeanAttribute(bean, attribute)) + } + } + + static Object getBeanAttribute(GroovyMBean bean, String attribute) { + try { + bean.getProperty(attribute) + } catch (AttributeNotFoundException e) { + logger.warning("Expected attribute ${attribute} not found in mbean ${bean.name()}") + null } } } diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy index a2233073b..e3ab6f3a5 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy @@ -88,13 +88,13 @@ class OtelHelper { * attribute value(s). The parameters map to the InstrumentHelper constructor. */ InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, Map labelFuncs, Map> attributes, Closure otelInstrument) { - def instrumentHelper = new InstrumentHelper(mBeanHelper, instrumentName, description, unit, labelFuncs, attributes, otelInstrument) + def instrumentHelper = new InstrumentHelper(mBeanHelper, instrumentName, description, unit, labelFuncs, attributes, otelInstrument, groovyMetricEnvironment) instrumentHelper.update() return instrumentHelper } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, Map labelFuncs, String attribute, Closure otelInstrument) { - instrument(mBeanHelper, instrumentName, description, unit, labelFuncs, [(attribute): [:] as Map], otelInstrument) + return instrument(mBeanHelper, instrumentName, description, unit, labelFuncs, [(attribute): [:] as Map], otelInstrument) } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, String attribute, Closure otelInstrument) { @@ -102,7 +102,7 @@ class OtelHelper { } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, String unit, Map> attributes, Closure otelInstrument) { - return instrument(mBeanHelper, instrumentName, description, unit, [:] as Map, attributes, otelInstrument) + return instrument(mBeanHelper, instrumentName, description, unit, [:] as Map, attributes, otelInstrument) } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, String attribute, Closure otelInstrument) { @@ -110,7 +110,7 @@ class OtelHelper { } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String description, Map> attributes, Closure otelInstrument) { - return instrument(mBeanHelper, instrumentName, description, OtelHelper.SCALAR, [:] as Map, attributes, otelInstrument) + return instrument(mBeanHelper, instrumentName, description, OtelHelper.SCALAR, [:] as Map, attributes, otelInstrument) } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, String attribute, Closure otelInstrument) { @@ -118,7 +118,7 @@ class OtelHelper { } InstrumentHelper instrument(MBeanHelper mBeanHelper, String instrumentName, Map> attributes, Closure otelInstrument) { - return instrument(mBeanHelper, instrumentName, "", OtelHelper.SCALAR, [:] as Map, attributes, otelInstrument) + return instrument(mBeanHelper, instrumentName, "", OtelHelper.SCALAR, [:] as Map, attributes, otelInstrument) } DoubleCounter doubleCounter(String name, String description, String unit) { @@ -193,75 +193,75 @@ class OtelHelper { return longHistogram(name, '') } - void doubleCounterCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerDoubleCounterCallback(name, description, unit, updater) + ObservableDoubleMeasurement doubleCounterCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerDoubleCounterCallback(name, description, unit, updater) } - void doubleCounterCallback(String name, String description, Consumer updater) { - doubleCounterCallback(name, description, SCALAR, updater) + ObservableDoubleMeasurement doubleCounterCallback(String name, String description, Consumer updater) { + return doubleCounterCallback(name, description, SCALAR, updater) } - void doubleCounterCallback(String name, Consumer updater) { - doubleCounterCallback(name, '', updater) + ObservableDoubleMeasurement doubleCounterCallback(String name, Consumer updater) { + return doubleCounterCallback(name, '', updater) } - void longCounterCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerLongCounterCallback(name, description, unit, updater) + ObservableLongMeasurement longCounterCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerLongCounterCallback(name, description, unit, updater) } - void longCounterCallback(String name, String description, Consumer updater) { - longCounterCallback(name, description, SCALAR, updater) + ObservableLongMeasurement longCounterCallback(String name, String description, Consumer updater) { + return longCounterCallback(name, description, SCALAR, updater) } - void longCounterCallback(String name, Consumer updater) { - longCounterCallback(name, '', updater) + ObservableLongMeasurement longCounterCallback(String name, Consumer updater) { + return longCounterCallback(name, '', updater) } - void doubleUpDownCounterCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerDoubleUpDownCounterCallback(name, description, unit, updater) + ObservableDoubleMeasurement doubleUpDownCounterCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerDoubleUpDownCounterCallback(name, description, unit, updater) } - void doubleUpDownCounterCallback(String name, String description, Consumer updater) { - doubleUpDownCounterCallback(name, description, SCALAR, updater) + ObservableDoubleMeasurement doubleUpDownCounterCallback(String name, String description, Consumer updater) { + return doubleUpDownCounterCallback(name, description, SCALAR, updater) } - void doubleUpDownCounterCallback(String name, Consumer updater) { - doubleUpDownCounterCallback(name, '', updater) + ObservableDoubleMeasurement doubleUpDownCounterCallback(String name, Consumer updater) { + return doubleUpDownCounterCallback(name, '', updater) } - void longUpDownCounterCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerLongUpDownCounterCallback(name, description, unit, updater) + ObservableLongMeasurement longUpDownCounterCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerLongUpDownCounterCallback(name, description, unit, updater) } - void longUpDownCounterCallback(String name, String description, Consumer updater) { - longUpDownCounterCallback(name, description, SCALAR, updater) + ObservableLongMeasurement longUpDownCounterCallback(String name, String description, Consumer updater) { + return longUpDownCounterCallback(name, description, SCALAR, updater) } - void longUpDownCounterCallback(String name, Consumer updater) { - longUpDownCounterCallback(name, '', updater) + ObservableLongMeasurement longUpDownCounterCallback(String name, Consumer updater) { + return longUpDownCounterCallback(name, '', updater) } - void doubleValueCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerDoubleValueCallback(name, description, unit, updater) + ObservableDoubleMeasurement doubleValueCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerDoubleValueCallback(name, description, unit, updater) } - void doubleValueCallback(String name, String description, Consumer updater) { - doubleValueCallback(name, description, SCALAR, updater) + ObservableDoubleMeasurement doubleValueCallback(String name, String description, Consumer updater) { + return doubleValueCallback(name, description, SCALAR, updater) } - void doubleValueCallback(String name, Consumer updater) { - doubleValueCallback(name, '', updater) + ObservableDoubleMeasurement doubleValueCallback(String name, Consumer updater) { + return doubleValueCallback(name, '', updater) } - void longValueCallback(String name, String description, String unit, Consumer updater) { - groovyMetricEnvironment.registerLongValueCallback(name, description, unit, updater) + ObservableLongMeasurement longValueCallback(String name, String description, String unit, Consumer updater) { + return groovyMetricEnvironment.registerLongValueCallback(name, description, unit, updater) } - void longValueCallback(String name, String description, Consumer updater) { - longValueCallback(name, description, SCALAR, updater) + ObservableLongMeasurement longValueCallback(String name, String description, Consumer updater) { + return longValueCallback(name, description, SCALAR, updater) } - void longValueCallback(String name, Consumer updater) { - longValueCallback(name, '', updater) + ObservableLongMeasurement longValueCallback(String name, Consumer updater) { + return longValueCallback(name, '', updater) } } diff --git a/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/InstrumenterHelperTest.java b/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/InstrumenterHelperTest.java index a9abdbef1..11737efb3 100644 --- a/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/InstrumenterHelperTest.java +++ b/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/InstrumenterHelperTest.java @@ -58,6 +58,7 @@ class InstrumenterHelperTest { // Will eventually be replaced with Jupiter extension in sdk-testing private SdkMeterProvider meterProvider; private InMemoryMetricReader metricReader; + private GroovyMetricEnvironment metricEnvironment; private OtelHelper otel; @@ -91,8 +92,8 @@ void confirmServerIsActive() { void setupOtel() { metricReader = InMemoryMetricReader.create(); meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); - - otel = new OtelHelper(jmxClient, new GroovyMetricEnvironment(meterProvider, "otel.test")); + metricEnvironment = new GroovyMetricEnvironment(meterProvider, "otel.test"); + otel = new OtelHelper(jmxClient, metricEnvironment); } @AfterEach @@ -688,7 +689,8 @@ void updateWithHelper( "1", labelFuncs, Collections.singletonMap(attribute, null), - instrument); + instrument, + metricEnvironment); instrumentHelper.update(); } @@ -702,7 +704,14 @@ void updateWithHelperMultiAttribute( Map> labelFuncs = new HashMap<>(); InstrumentHelper instrumentHelper = new InstrumentHelper( - mBeanHelper, instrumentName, description, "1", labelFuncs, attributes, instrument); + mBeanHelper, + instrumentName, + description, + "1", + labelFuncs, + attributes, + instrument, + metricEnvironment); instrumentHelper.update(); } From fe3a41353b146e56a4ca5b00ff83da7ab9111274 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 27 Jul 2023 04:09:09 -0700 Subject: [PATCH 012/108] Consolidate gradle enterprise version bumps (#984) --- .github/renovate.json5 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index aa1e9d48f..294d4c1b8 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -4,6 +4,14 @@ "config:base" ], "packageRules": [ + { + "matchPackagePrefixes": ["ch.qos.logback:"], + "groupName": "logback packages" + }, + { + "matchPackagePrefixes": ["com.gradle.enterprise"], + "groupName": "gradle enterprise packages" + }, { // junit-pioneer 2+ requires Java 11+ "matchPackageNames": ["org.junit-pioneer:junit-pioneer"], From 35b4e7a045dc25ddb6d8490eee46a9b10abedf6a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:13:11 -0700 Subject: [PATCH 013/108] Update dependency com.google.guava:guava-bom to v32.1.2-jre (#987) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index b5d0a3f8d..3081e63ba 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -13,7 +13,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", - "com.google.guava:guava-bom:32.1.1-jre", + "com.google.guava:guava-bom:32.1.2-jre", "com.linecorp.armeria:armeria-bom:1.24.3", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.56.1", From d0236147c7606f1a0043f79a217438fb600e9993 Mon Sep 17 00:00:00 2001 From: jason plumb <75337021+breedx-splk@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:20:25 -0700 Subject: [PATCH 014/108] [disk-buffering] Migrate StorageFile to FileOperations (#986) --- .../internal/storage/FolderManager.java | 6 +-- .../storage/files/FileOperations.java | 23 ++++++++++ .../internal/storage/files/ReadableFile.java | 10 ++++- .../internal/storage/files/StorageFile.java | 23 ---------- .../internal/storage/files/WritableFile.java | 12 +++++- .../internal/storage/FolderManagerTest.java | 43 +++++++++---------- .../storage/files/WritableFileTest.java | 2 +- 7 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/FileOperations.java delete mode 100644 disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/StorageFile.java diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java index 5e0a5e1f6..45e66fdeb 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java @@ -77,7 +77,7 @@ private File findReadableFile() throws IOException { // Checking if the oldest available file is currently the writable file. if (oldestFileAvailable != null && currentWritableFile != null - && oldestFileAvailable.equals(currentWritableFile.file)) { + && oldestFileAvailable.equals(currentWritableFile.getFile())) { currentWritableFile.close(); } return oldestFileAvailable; @@ -88,7 +88,7 @@ private int purgeExpiredFilesIfAny(File[] existingFiles, long currentTimeMillis) int filesDeleted = 0; for (File existingFile : existingFiles) { if (hasExpiredForReading(currentTimeMillis, Long.parseLong(existingFile.getName()))) { - if (currentReadableFile != null && existingFile.equals(currentReadableFile.file)) { + if (currentReadableFile != null && existingFile.equals(currentReadableFile.getFile())) { currentReadableFile.close(); } if (existingFile.delete()) { @@ -103,7 +103,7 @@ private void removeOldestFileIfSpaceIsNeeded(File[] existingFiles) throws IOExce if (existingFiles.length > 0) { if (isNeededToClearSpaceForNewFile(existingFiles)) { File oldest = getOldest(existingFiles); - if (currentReadableFile != null && oldest.equals(currentReadableFile.file)) { + if (currentReadableFile != null && oldest.equals(currentReadableFile.getFile())) { currentReadableFile.close(); } if (!oldest.delete()) { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/FileOperations.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/FileOperations.java new file mode 100644 index 000000000..21544a991 --- /dev/null +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/FileOperations.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.storage.files; + +import java.io.Closeable; +import java.io.File; + +public interface FileOperations extends Closeable { + long getSize(); + + boolean hasExpired(); + + boolean isClosed(); + + File getFile(); + + default String getFileName() { + return getFile().getName(); + } +} diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFile.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFile.java index 2f22a29c1..049de1bd9 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFile.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFile.java @@ -33,7 +33,8 @@ * *

More information on the overall storage process in the CONTRIBUTING.md file. */ -public final class ReadableFile extends StorageFile { +public final class ReadableFile implements FileOperations { + private final File file; private final int originalFileSize; private final StreamReader reader; private final FileTransferUtil fileTransferUtil; @@ -62,7 +63,7 @@ public ReadableFile( StorageConfiguration configuration, StreamReader.Factory readerFactory) throws IOException { - super(file); + this.file = file; this.clock = clock; expireTimeMillis = createdTimeMillis + configuration.getMaxFileAgeForReadMillis(); originalFileSize = (int) file.length(); @@ -139,6 +140,11 @@ public synchronized boolean isClosed() { return isClosed.get(); } + @Override + public File getFile() { + return file; + } + @Override public synchronized void close() throws IOException { if (isClosed.compareAndSet(false, true)) { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/StorageFile.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/StorageFile.java deleted file mode 100644 index ea87ace9b..000000000 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/StorageFile.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.disk.buffering.internal.storage.files; - -import java.io.Closeable; -import java.io.File; - -public abstract class StorageFile implements Closeable { - public final File file; - - public StorageFile(File file) { - this.file = file; - } - - public abstract long getSize(); - - public abstract boolean hasExpired(); - - public abstract boolean isClosed(); -} diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFile.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFile.java index e2a4682b4..f72fd7d6c 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFile.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFile.java @@ -16,7 +16,10 @@ import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; -public final class WritableFile extends StorageFile { +public final class WritableFile implements FileOperations { + + private final File file; + private final StorageConfiguration configuration; private final Clock clock; private final long expireTimeMillis; @@ -27,7 +30,7 @@ public final class WritableFile extends StorageFile { public WritableFile( File file, long createdTimeMillis, StorageConfiguration configuration, Clock clock) throws IOException { - super(file); + this.file = file; this.configuration = configuration; this.clock = clock; expireTimeMillis = createdTimeMillis + configuration.getMaxFileAgeForWriteMillis(); @@ -75,6 +78,11 @@ public synchronized boolean isClosed() { return isClosed.get(); } + @Override + public File getFile() { + return file; + } + @Override public synchronized void close() throws IOException { if (isClosed.compareAndSet(false, true)) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java index 7db0e90bd..9b41d6f71 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.mock; import io.opentelemetry.contrib.disk.buffering.internal.storage.files.ReadableFile; -import io.opentelemetry.contrib.disk.buffering.internal.storage.files.StorageFile; import io.opentelemetry.contrib.disk.buffering.internal.storage.files.WritableFile; import io.opentelemetry.sdk.common.Clock; import java.io.File; @@ -45,9 +44,9 @@ void setUp() { void createWritableFile_withTimeMillisAsName() throws IOException { doReturn(MILLISECONDS.toNanos(1000L)).when(clock).now(); - StorageFile file = folderManager.createWritableFile(); + WritableFile file = folderManager.createWritableFile(); - assertEquals("1000", file.file.getName()); + assertEquals("1000", file.getFileName()); } @Test @@ -62,11 +61,11 @@ void createWritableFile_andRemoveOldestOne_whenTheAvailableFolderSpaceIsNotEnoug fillWithBytes(existingFile3, MAX_FILE_SIZE); doReturn(1500L).when(clock).now(); - StorageFile file = folderManager.createWritableFile(); + WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.file); - assertNotEquals(existingFile2, file.file); - assertNotEquals(existingFile3, file.file); + assertNotEquals(existingFile1, file.getFile()); + assertNotEquals(existingFile2, file.getFile()); + assertNotEquals(existingFile3, file.getFile()); assertTrue(existingFile2.exists()); assertTrue(existingFile3.exists()); assertFalse(existingFile1.exists()); @@ -87,7 +86,7 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_anNoOtherReadableFilesAreA ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(writableFile.file, readableFile.file); + assertEquals(writableFile.getFile(), readableFile.getFile()); assertTrue(writableFile.isClosed()); } @@ -105,7 +104,7 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_anNoOtherReadableFilesAreA doReturn(MILLISECONDS.toNanos(1000L + MIN_FILE_AGE_FOR_READ_MILLIS)).when(clock).now(); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(existingFile1, readableFile.file); + assertEquals(existingFile1, readableFile.getFile()); folderManager.createWritableFile(); @@ -127,11 +126,11 @@ void createWritableFile_andDoNotRemoveOldestOne_ifAtLeastOneExpiredFileIsPurged( fillWithBytes(existingFile3, MAX_FILE_SIZE); doReturn(MILLISECONDS.toNanos(11_000L)).when(clock).now(); - StorageFile file = folderManager.createWritableFile(); + WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.file); - assertNotEquals(existingFile2, file.file); - assertNotEquals(existingFile3, file.file); + assertNotEquals(existingFile1, file.getFile()); + assertNotEquals(existingFile2, file.getFile()); + assertNotEquals(existingFile3, file.getFile()); assertTrue(existingFile2.exists()); assertTrue(existingFile1.exists()); assertFalse(existingFile3.exists()); @@ -146,11 +145,11 @@ void purgeExpiredForReadFiles_whenCreatingNewOne() throws IOException { createFiles(expiredReadableFile, expiredWritableFile); doReturn(MILLISECONDS.toNanos(11_500L)).when(clock).now(); - StorageFile file = folderManager.createWritableFile(); + WritableFile file = folderManager.createWritableFile(); assertFalse(expiredReadableFile.exists()); assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.file); + assertNotEquals(expiredWritableFile, file.getFile()); } @Test @@ -163,16 +162,16 @@ void closeExpiredReadableFileInUseIfAny_whenPurgingExpiredForReadFiles_whenCreat doReturn(MILLISECONDS.toNanos(900 + MIN_FILE_AGE_FOR_READ_MILLIS)).when(clock).now(); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(expiredReadableFileBeingRead, readableFile.file); + assertEquals(expiredReadableFileBeingRead, readableFile.getFile()); doReturn(MILLISECONDS.toNanos(11_500L)).when(clock).now(); - StorageFile file = folderManager.createWritableFile(); + WritableFile file = folderManager.createWritableFile(); assertFalse(expiredReadableFile.exists()); assertFalse(expiredReadableFileBeingRead.exists()); assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.file); + assertNotEquals(expiredWritableFile, file.getFile()); assertTrue(readableFile.isClosed()); } @@ -186,9 +185,9 @@ void provideFileForRead_afterItsMinFileAgeForReadTimePassed() throws IOException File readableFile = new File(rootDir, String.valueOf(readableFileCreationTime)); createFiles(writableFile, readableFile); - StorageFile file = folderManager.getReadableFile(); + ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFile, file.file); + assertEquals(readableFile, file.getFile()); } @Test @@ -203,9 +202,9 @@ void provideOldestFileForRead_whenMultipleReadableFilesAreAvailable() throws IOE File readableFileNewer = new File(rootDir, String.valueOf(newerReadableFileCreationTime)); createFiles(writableFile, readableFileNewer, readableFileOlder); - StorageFile file = folderManager.getReadableFile(); + ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFileOlder, file.file); + assertEquals(readableFileOlder, file.getFile()); } @Test diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java index 5008fc210..b10631f9c 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java @@ -116,6 +116,6 @@ private static byte[] getByteArrayLine(String line) { } private List getWrittenLines() throws IOException { - return Files.readAllLines(writableFile.file.toPath()); + return Files.readAllLines(writableFile.getFile().toPath()); } } From 175effc610145c1e494d29c4f81d3bed30597c46 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:20:45 -0700 Subject: [PATCH 015/108] Update dependency io.grpc:grpc-bom to v1.57.0 (#985) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 3081e63ba..92b7d3600 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -16,7 +16,7 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:32.1.2-jre", "com.linecorp.armeria:armeria-bom:1.24.3", "org.junit:junit-bom:5.10.0", - "io.grpc:grpc-bom:1.56.1", + "io.grpc:grpc-bom:1.57.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", "org.testcontainers:testcontainers-bom:1.18.3" ) From c91adec0c8c2eae300e062766dc12b1dcd177fe1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 21:57:30 +0000 Subject: [PATCH 016/108] Update dependency io.grpc:grpc-bom to v1.57.1 (#988) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 92b7d3600..662e62309 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -16,7 +16,7 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:32.1.2-jre", "com.linecorp.armeria:armeria-bom:1.24.3", "org.junit:junit-bom:5.10.0", - "io.grpc:grpc-bom:1.57.0", + "io.grpc:grpc-bom:1.57.1", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", "org.testcontainers:testcontainers-bom:1.18.3" ) From 9aa5505baa81aea4f56f7dc055e8355ecd62fa4b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 18:01:46 -0700 Subject: [PATCH 017/108] Update dependency com.uber.nullaway:nullaway to v0.10.12 (#991) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 662e62309..9775fad89 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -53,7 +53,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", - "com.uber.nullaway:nullaway:0.10.11", + "com.uber.nullaway:nullaway:0.10.12", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From f75d7b5c4db760ea2f32c179fd2734c2c4506421 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 3 Aug 2023 02:29:13 -0700 Subject: [PATCH 018/108] Update release instructions to reflect dependabot -> renovate (#993) --- .github/config/markdown-link-check-config.json | 4 ++-- .github/scripts/draft-change-log-entries.sh | 2 +- .github/scripts/generate-release-contributors.sh | 2 ++ RELEASING.md | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/config/markdown-link-check-config.json b/.github/config/markdown-link-check-config.json index 28f3d097c..10ebecdb0 100644 --- a/.github/config/markdown-link-check-config.json +++ b/.github/config/markdown-link-check-config.json @@ -2,10 +2,10 @@ "retryOn429": true, "ignorePatterns": [ { - "pattern": "^https://github\\.com/open-telemetry/opentelemetry-java-contrib/network/updates$" + "pattern": "^https://developer\\.mend\\.io/github/open-telemetry/opentelemetry-java-contrib$" }, { - "pattern": "^https://github.com/open-telemetry/opentelemetry-java-contrib/pulls/app%2Fdependabot$" + "pattern": "^https://github.com/open-telemetry/opentelemetry-java-contrib/pulls/app%2Frenovate" } ] } diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh index 98474c6f5..94f38b906 100755 --- a/.github/scripts/draft-change-log-entries.sh +++ b/.github/scripts/draft-change-log-entries.sh @@ -48,7 +48,7 @@ for component in */ ; do component_name=${component_names[$component]:=$component} commits=$(git log --reverse \ --perl-regexp \ - --author='^(?!dependabot\[bot\] )' \ + --author='^(?!renovate\[bot\] )' \ --pretty=format:"- %s" \ "$range" \ "$component") diff --git a/.github/scripts/generate-release-contributors.sh b/.github/scripts/generate-release-contributors.sh index 8ee98c679..1fffa9279 100755 --- a/.github/scripts/generate-release-contributors.sh +++ b/.github/scripts/generate-release-contributors.sh @@ -79,11 +79,13 @@ query($q: String!, $endCursor: String) { | sed 's/^\["//' \ | sed 's/".*//') +# TODO (trask) can remove dependabot line after next release echo $contributors1 $contributors2 \ | sed 's/ /\n/g' \ | sort -uf \ | grep -v linux-foundation-easycla \ | grep -v github-actions \ | grep -v dependabot \ + | grep -v renovate \ | grep -v opentelemetrybot \ | sed 's/^/@/' diff --git a/RELEASING.md b/RELEASING.md index 874aabef1..afb1b8162 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -18,9 +18,9 @@ the second Monday of the month (roughly a couple of days after the monthly minor ## Preparing a new major or minor release -* Check that [dependabot has run](https://github.com/open-telemetry/opentelemetry-java-contrib/network/updates) +* Check that [renovate has run](https://developer.mend.io/github/open-telemetry/opentelemetry-java-contrib) sometime in the past day and that all - [dependabot PRs](https://github.com/open-telemetry/opentelemetry-java-contrib/pulls/app%2Fdependabot) + [renovate PRs](https://github.com/open-telemetry/opentelemetry-java-contrib/pulls/app%2Frenovate) have been merged. * Check that the OpenTelemetry SDK and Instrumentation versions have been updated to the latest release. * Close the [release milestone](https://github.com/open-telemetry/opentelemetry-java-contrib/milestones) From d50127bd1a4721d4c88ca52f1887f59e5483d216 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 3 Aug 2023 10:36:42 -0700 Subject: [PATCH 019/108] Update errorProneVersion to v2.21.0 (#989) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Trask Stalnaker --- .../contrib/awsxray/AwsMetricAttributeGenerator.java | 6 +++--- dependencyManagement/build.gradle.kts | 2 +- .../io/opentelemetry/contrib/jfr/connection/JfrStream.java | 6 +++--- .../contrib/jfr/connection/RecordingOptions.java | 6 ++---- .../contrib/attach/core/CoreRuntimeAttach.java | 1 + .../java/io/opentelemetry/contrib/attach/RuntimeAttach.java | 1 + .../contrib/staticinstrumenter/agent/main/ClassArchive.java | 1 + 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java index 7b27d39e3..bf55d061e 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java @@ -266,7 +266,7 @@ private static String generateIngressOperation(SpanData span) { // the more levels/parts we get from API path the higher chance for getting high cardinality // data if (httpTarget != null) { - operation = extractAPIPathValue(httpTarget); + operation = extractApiPathValue(httpTarget); if (isKeyPresent(span, HTTP_METHOD)) { String httpMethod = span.getAttributes().get(HTTP_METHOD); if (httpMethod != null) { @@ -290,7 +290,7 @@ private static String generateRemoteOperation(SpanData span) { URL url; if (httpUrl != null) { url = new URL(httpUrl); - remoteOperation = extractAPIPathValue(url.getPath()); + remoteOperation = extractApiPathValue(url.getPath()); } } catch (MalformedURLException e) { logger.log(Level.FINEST, "invalid http.url attribute: ", httpUrl); @@ -312,7 +312,7 @@ private static String generateRemoteOperation(SpanData span) { * @param httpTarget http request target string value. Eg, /payment/1234 * @return the first part from the http target. Eg, /payment */ - private static String extractAPIPathValue(String httpTarget) { + private static String extractApiPathValue(String httpTarget) { if (httpTarget == null || httpTarget.isEmpty()) { return "/"; } diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 9775fad89..0867ced87 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -23,7 +23,7 @@ val DEPENDENCY_BOMS = listOf( val autoServiceVersion = "1.1.1" val autoValueVersion = "1.10.2" -val errorProneVersion = "2.19.1" +val errorProneVersion = "2.21.0" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" val slf4jVersion = "2.0.7" diff --git a/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/JfrStream.java b/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/JfrStream.java index f9102dcfc..851b02cde 100644 --- a/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/JfrStream.java +++ b/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/JfrStream.java @@ -37,7 +37,7 @@ public static long getDefaultBlockSize() { // Initialize buffer to empty array to subvert null checks. private byte[] buffer = new byte[0]; private int index = 0; - private boolean reachedEOF = false; + private boolean reachedEndOfFile = false; // There is a recording id and an id you get from the recording for the stream. // streamId is the id for the stream. private final long streamid; @@ -53,7 +53,7 @@ public static long getDefaultBlockSize() { @Override public int read() throws IOException { - if (!reachedEOF && index == 0) { + if (!reachedEndOfFile && index == 0) { Object[] params = new Object[] {streamid}; String[] signature = new String[] {long.class.getName()}; try { @@ -63,7 +63,7 @@ public int read() throws IOException { } } - if (reachedEOF || (reachedEOF = (buffer == null))) { + if (reachedEndOfFile || (reachedEndOfFile = (buffer == null))) { return -1; } diff --git a/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/RecordingOptions.java b/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/RecordingOptions.java index 55fff2f90..119c8ce8d 100644 --- a/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/RecordingOptions.java +++ b/jfr-connection/src/main/java/io/opentelemetry/contrib/jfr/connection/RecordingOptions.java @@ -43,17 +43,15 @@ */ public class RecordingOptions { - /* Default values of some options. */ - private static final String EMPTY_STRING = ""; private static final String NO_LIMIT = "0"; /* Options hash table keys. */ private enum Option { - NAME("name", EMPTY_STRING), + NAME("name", ""), MAX_AGE("maxAge", NO_LIMIT), MAX_SIZE("maxSize", NO_LIMIT), DUMP_ON_EXIT("dumpOnExit", "false"), - DESTINATION("destination", EMPTY_STRING), + DESTINATION("destination", ""), DISK("disk", "false"), DURATION("duration", NO_LIMIT); diff --git a/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java b/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java index ede436edb..dab3217fb 100644 --- a/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java +++ b/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java @@ -34,6 +34,7 @@ public CoreRuntimeAttach(String agentJarResourceName) { * Attach the OpenTelemetry Java agent to the current JVM. The attachment must be requested at the * beginning of the main method. */ + @SuppressWarnings("MemberName") public void attachJavaagentToCurrentJVM() { if (!shouldAttach()) { return; diff --git a/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java b/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java index 21500b9d1..9c97720a4 100644 --- a/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java +++ b/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java @@ -14,6 +14,7 @@ public final class RuntimeAttach { * Attach the OpenTelemetry Java agent to the current JVM. The attachment must be requested at the * beginning of the main method. */ + @SuppressWarnings("MemberName") public static void attachJavaagentToCurrentJVM() { CoreRuntimeAttach distroRuntimeAttach = new CoreRuntimeAttach("/otel-agent.jar"); diff --git a/static-instrumenter/agent-instrumenter/src/main/java/io/opentelemetry/contrib/staticinstrumenter/agent/main/ClassArchive.java b/static-instrumenter/agent-instrumenter/src/main/java/io/opentelemetry/contrib/staticinstrumenter/agent/main/ClassArchive.java index 155101a18..517fc96ed 100644 --- a/static-instrumenter/agent-instrumenter/src/main/java/io/opentelemetry/contrib/staticinstrumenter/agent/main/ClassArchive.java +++ b/static-instrumenter/agent-instrumenter/src/main/java/io/opentelemetry/contrib/staticinstrumenter/agent/main/ClassArchive.java @@ -65,6 +65,7 @@ private static boolean isEntryDuplicate(ZipException ze) { return ze.getMessage() != null && ze.getMessage().contains("duplicate"); } + @SuppressWarnings("BanClassLoader") private InputStream getInputStreamForEntry(JarEntry inEntry, ZipEntry outEntry) throws IOException { From aa0ca10242c9e5fe7e3af9510f8a08b5d748d605 Mon Sep 17 00:00:00 2001 From: Alex Kats <56042997+akats7@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:02:36 -0400 Subject: [PATCH 020/108] Added transformation closure to MBeanHelper (#960) --- jmx-metrics/README.md | 20 ++++ .../contrib/jmxmetrics/MBeanHelper.groovy | 30 +++++- .../contrib/jmxmetrics/OtelHelper.groovy | 11 +++ .../contrib/jmxmetrics/MBeanHelperTest.java | 97 ++++++++++++++++++- 4 files changed, 150 insertions(+), 8 deletions(-) diff --git a/jmx-metrics/README.md b/jmx-metrics/README.md index 29e2db023..407c20845 100644 --- a/jmx-metrics/README.md +++ b/jmx-metrics/README.md @@ -160,6 +160,26 @@ In cases where you'd like to share instrument names while creating datapoints fo - `otel.instrument(MBeanHelper mBeanHelper, String name, String description, Map> attributeLabelFuncs, Closure instrument)` - `unit` is "1" and `labelFuncs` are empty map. - `otel.instrument(MBeanHelper mBeanHelper, String name, Map> attributeLabelFuncs, Closure instrument)` - `description` is empty string, `unit` is "1" and `labelFuncs` are empty map +### MBeans with non-numeric attributes + +In cases where you'd like to create metrics based on non-numeric MBean attributes, the mbean helper methods provide the ability to pass a map of closures, to transform the original extracted attribute into one that can be consumed by the instrument callbacks. + +- `otel.mbean(String objectNameStr, Map> attributeTransformation)` + +- `otel.mbeans(String objectNameStr, Map> attributeTransformation)` + +- `otel.mbeans(List objectNameStrs, Map> attributeTransformation)` + +These methods provide the ability to easily convert the attributes you will be extracting from the mbeans, at the time of creation for the MBeanHelper. + + ```groovy + // In this example a String based health attribute is converted to a numeric binary value + def someBean = otel.mbean( + "SomeMBean", ["CustomAttrFromString": { mbean -> mbean.getProperty("Attribute") == "running" ? 1 : 0 }] + ) + otel.instrument(someBean, "my-metric", "CustomAttrFromString", otel.&longUpDownCounterCallback) + ``` + ## OpenTelemetry Synchronous Instrument Helpers - `otel.doubleCounter(String name, String description, String unit)` diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy index 1ba98467e..9cabdecf2 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/MBeanHelper.groovy @@ -35,6 +35,7 @@ class MBeanHelper { private final JmxClient jmxClient private final boolean isSingle private final List objectNames + private final Map attributeTransformation private List mbeans @@ -42,15 +43,31 @@ class MBeanHelper { this.jmxClient = jmxClient this.objectNames = Collections.unmodifiableList([objectName]) this.isSingle = isSingle + this.attributeTransformation = [:] as Map> } MBeanHelper(JmxClient jmxClient, List objectNames) { this.jmxClient = jmxClient this.objectNames = Collections.unmodifiableList(objectNames) this.isSingle = false + this.attributeTransformation = [:] as Map> } - @PackageScope static List queryJmx(JmxClient jmxClient, String objNameStr) { + MBeanHelper(JmxClient jmxClient, String objectName, boolean isSingle, Map> attributeTransformation ) { + this.jmxClient = jmxClient + this.objectNames = Collections.unmodifiableList([objectName]) + this.isSingle = isSingle + this.attributeTransformation = attributeTransformation + } + + MBeanHelper(JmxClient jmxClient, List objectNames, Map> attributeTransformation) { + this.jmxClient = jmxClient + this.objectNames = Collections.unmodifiableList(objectNames) + this.isSingle = false + this.attributeTransformation = attributeTransformation + } + + @PackageScope static List queryJmx(JmxClient jmxClient, String objNameStr) { return queryJmx(jmxClient, new ObjectName(objNameStr)) } @@ -88,7 +105,7 @@ class MBeanHelper { def ofInterest = isSingle ? [mbeans[0]]: mbeans return ofInterest.collect { - getBeanAttribute(it, attribute) + getBeanAttributeWithTransform(it, attribute) } } @@ -100,13 +117,18 @@ class MBeanHelper { def ofInterest = isSingle ? [mbeans[0]]: mbeans return [ofInterest, attributes].combinations().collect { pair -> def (bean, attribute) = pair - new Tuple3(bean, attribute, getBeanAttribute(bean, attribute)) + new Tuple3(bean, attribute, getBeanAttributeWithTransform(bean, attribute)) } } + Object getBeanAttributeWithTransform(GroovyMBean bean, String attribute){ + def transformationClosure = attributeTransformation.get(attribute); + return transformationClosure != null ? transformationClosure(bean) : getBeanAttribute(bean, attribute) + } + static Object getBeanAttribute(GroovyMBean bean, String attribute) { try { - bean.getProperty(attribute) + bean.getProperty(attribute) } catch (AttributeNotFoundException e) { logger.warning("Expected attribute ${attribute} not found in mbean ${bean.name()}") null diff --git a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy index e3ab6f3a5..49f071d6a 100644 --- a/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy +++ b/jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/OtelHelper.groovy @@ -83,6 +83,17 @@ class OtelHelper { return mbeanHelper } + MBeanHelper mbean(String objNameStr, Map> attributeTransformation) { + def mbeanHelper = new MBeanHelper(jmxClient, objNameStr, true, attributeTransformation) + mbeanHelper.fetch() + return mbeanHelper + } + + MBeanHelper mbeans(List objNameStrs, Map> attributeTransformation) { + def mbeanHelper = new MBeanHelper(jmxClient, objNameStrs, attributeTransformation) + mbeanHelper.fetch() + return mbeanHelper + } /** * Returns an updated @{link InstrumentHelper} associated with the provided {@link MBeanHelper} and its specified * attribute value(s). The parameters map to the InstrumentHelper constructor. diff --git a/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/MBeanHelperTest.java b/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/MBeanHelperTest.java index 6dbecd06f..8f696ee5b 100644 --- a/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/MBeanHelperTest.java +++ b/jmx-metrics/src/test/java/io/opentelemetry/contrib/jmxmetrics/MBeanHelperTest.java @@ -9,13 +9,17 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import groovy.lang.Closure; +import groovy.util.Eval; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; +import java.util.stream.Stream; import javax.management.MBeanServer; import javax.management.ObjectInstance; import javax.management.ObjectName; @@ -81,7 +85,6 @@ void multiObj() throws Exception { MBeanHelper mBeanHelper = new MBeanHelper(jmxClient, Arrays.asList(thingName + ",thing=0", thingName + ",thing=1")); mBeanHelper.fetch(); - assertThat(mBeanHelper.getAttribute("SomeAttribute")) .hasSameElementsAs( IntStream.range(0, 2).mapToObj(Integer::toString).collect(Collectors.toList())); @@ -116,6 +119,77 @@ void multiple() throws Exception { IntStream.range(0, 100).mapToObj(unused -> null).collect(Collectors.toList())); } + @Test + void transform() throws Exception { + String thingName = "io.opentelemetry.contrib.jmxmetrics:type=transform"; + Thing thing = new Thing("someValue"); + mbeanServer.registerMBean(thing, new ObjectName(thingName)); + Map> map = + Stream.of( + new Object[][] { + { + "SomeAttribute", + Eval.me( + "{mbean -> mbean.getProperty(\"SomeAttribute\") == 'someValue' ? 'otherValue' : 'someValue'}") + }, + }) + .collect(Collectors.toMap(data -> (String) data[0], data -> (Closure) data[1])); + MBeanHelper mBeanHelper = new MBeanHelper(jmxClient, thingName + ",*", true, map); + mBeanHelper.fetch(); + + assertThat(mBeanHelper.getAttribute("SomeAttribute")) + .hasSameElementsAs(Stream.of(new String[] {"otherValue"}).collect(Collectors.toList())); + } + + @Test + void transformMultipleAttributes() throws Exception { + String thingName = "io.opentelemetry.contrib.jmxmetrics:type=transformMultiple"; + Thing thing1 = new Thing("someValue", "anotherValue"); + ObjectName mbeanName = new ObjectName(thingName); + mbeanServer.registerMBean(thing1, mbeanName); + Map> map = + Stream.of( + new Object[][] { + { + "SomeAttribute", + Eval.me( + "{mbean -> mbean.getProperty(\"SomeAttribute\") == 'someValue' ? 'newValue' : 'someValue'}") + }, + { + "AnotherAttribute", + Eval.me( + "{mbean -> mbean.getProperty(\"AnotherAttribute\") == 'anotherValue' ? 'anotherNewValue' : 'anotherValue'}") + }, + }) + .collect(Collectors.toMap(data -> (String) data[0], data -> (Closure) data[1])); + MBeanHelper mBeanHelper = new MBeanHelper(jmxClient, thingName + ",*", true, map); + mBeanHelper.fetch(); + + assertThat(mBeanHelper.getAttribute("SomeAttribute")) + .hasSameElementsAs(Stream.of(new String[] {"newValue"}).collect(Collectors.toList())); + assertThat(mBeanHelper.getAttribute("AnotherAttribute")) + .hasSameElementsAs( + Stream.of(new String[] {"anotherNewValue"}).collect(Collectors.toList())); + } + + @Test + void customAttribute() throws Exception { + String thingName = "io.opentelemetry.contrib.jmxmetrics:type=custom"; + Thing thing = new Thing(""); + mbeanServer.registerMBean(thing, new ObjectName(thingName)); + Map> map = + Stream.of( + new Object[][] { + {"CustomAttribute", Eval.me("{mbean -> 'customValue'}")}, + }) + .collect(Collectors.toMap(data -> (String) data[0], data -> (Closure) data[1])); + MBeanHelper mBeanHelper = new MBeanHelper(jmxClient, thingName, true, map); + mBeanHelper.fetch(); + + assertThat(mBeanHelper.getAttribute("CustomAttribute")) + .hasSameElementsAs(Stream.of(new String[] {"customValue"}).collect(Collectors.toList())); + } + private static void registerThings(String thingName) throws Exception { for (int i = 0; i < 100; i++) { Thing thing = new Thing(Integer.toString(i)); @@ -127,19 +201,34 @@ private static void registerThings(String thingName) throws Exception { public interface ThingMBean { String getSomeAttribute(); + + String getAnotherAttribute(); } static class Thing implements ThingMBean { - private final String attrValue; + private final String attrValue1; + + private final String attrValue2; Thing(String attrValue) { - this.attrValue = attrValue; + this.attrValue1 = attrValue; + this.attrValue2 = ""; + } + + Thing(String attrValue1, String attrValue2) { + this.attrValue1 = attrValue1; + this.attrValue2 = attrValue2; } @Override public String getSomeAttribute() { - return attrValue; + return attrValue1; + } + + @Override + public String getAnotherAttribute() { + return attrValue2; } } } From 26760e7e8a6b8c504838239ae369c8a51d02e818 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 16:52:43 -0700 Subject: [PATCH 021/108] Update errorProneVersion to v2.21.1 (#994) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 0867ced87..751cdfc3a 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -23,7 +23,7 @@ val DEPENDENCY_BOMS = listOf( val autoServiceVersion = "1.1.1" val autoValueVersion = "1.10.2" -val errorProneVersion = "2.21.0" +val errorProneVersion = "2.21.1" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" val slf4jVersion = "2.0.7" From 5d189842485f374d916664df9fdee0bb01790d39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 15:31:54 -0700 Subject: [PATCH 022/108] Update dependency net.bytebuddy:byte-buddy-agent to v1.14.6 (#995) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- runtime-attach/runtime-attach-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-attach/runtime-attach-core/build.gradle.kts b/runtime-attach/runtime-attach-core/build.gradle.kts index 7fa48a71b..41d65bae4 100644 --- a/runtime-attach/runtime-attach-core/build.gradle.kts +++ b/runtime-attach/runtime-attach-core/build.gradle.kts @@ -7,7 +7,7 @@ description = "To help in create an OpenTelemetry distro able to runtime attach otelJava.moduleName.set("io.opentelemetry.contrib.attach.core") dependencies { - implementation("net.bytebuddy:byte-buddy-agent:1.14.5") + implementation("net.bytebuddy:byte-buddy-agent:1.14.6") // Used by byte-buddy but not brought in as a transitive dependency. compileOnly("com.google.code.findbugs:annotations") From 015dd0a00c4039b47c633e8745f1a91f1187704a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:43:39 -0700 Subject: [PATCH 023/108] Update dependency io.micrometer:micrometer-core to v1.11.3 (#996) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index e6b136f32..7560d025d 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.11.2") + testImplementation("io.micrometer:micrometer-core:1.11.3") } testing { From 06b613fe9629a74c4cf0a456175efb764aa177fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:43:46 -0700 Subject: [PATCH 024/108] Update dependency io.micrometer:micrometer-registry-prometheus to v1.11.3 (#997) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index 7560d025d..64db724a8 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -26,7 +26,7 @@ testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.11.2") + implementation("io.micrometer:micrometer-registry-prometheus:1.11.3") } } } From bc93856e1bf92aa8ae97f13fe1f270db0bb00210 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Tue, 15 Aug 2023 07:44:21 -0700 Subject: [PATCH 025/108] Group micrometer renovate updates (#998) --- .github/renovate.json5 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 294d4c1b8..0f7d57695 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -8,6 +8,10 @@ "matchPackagePrefixes": ["ch.qos.logback:"], "groupName": "logback packages" }, + { + "matchPackagePrefixes": ["io.micrometer:"], + "groupName": "micrometer packages" + }, { "matchPackagePrefixes": ["com.gradle.enterprise"], "groupName": "gradle enterprise packages" From 2fcaa202fdb49254eb635a0e8ec4c8f81635c3e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:10:07 -0700 Subject: [PATCH 026/108] Update dependency io.grpc:grpc-bom to v1.57.2 (#1001) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 751cdfc3a..2d257f9fd 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -16,7 +16,7 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:32.1.2-jre", "com.linecorp.armeria:armeria-bom:1.24.3", "org.junit:junit-bom:5.10.0", - "io.grpc:grpc-bom:1.57.1", + "io.grpc:grpc-bom:1.57.2", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", "org.testcontainers:testcontainers-bom:1.18.3" ) From 52658537aae25ebd7b91f68fe2806b999b10cf31 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:10:36 -0700 Subject: [PATCH 027/108] Update autoValueVersion to v1.10.3 (#1000) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- disk-buffering/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 2d257f9fd..2789966dc 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -22,7 +22,7 @@ val DEPENDENCY_BOMS = listOf( ) val autoServiceVersion = "1.1.1" -val autoValueVersion = "1.10.2" +val autoValueVersion = "1.10.3" val errorProneVersion = "2.21.1" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 2be29ccc9..135cc3776 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -15,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -val autovalueVersion = "1.10.2" +val autovalueVersion = "1.10.3" dependencies { api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-exporter-otlp-common") From 224cf3068006078272066367debe7573fc1dd599 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 16 Aug 2023 03:19:08 -0700 Subject: [PATCH 028/108] Fix gradle deprecated warning (#1003) --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 2789966dc..05ca18fc7 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -86,7 +86,7 @@ dependencies { } fun isNonStable(version: String): Boolean { - val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) } + val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) } val regex = "^[0-9,.v-]+(-r)?$".toRegex() val isGuava = version.endsWith("-jre") val isStable = stableKeyword || regex.matches(version) || isGuava From ace301ed984cb4b1a67ce5b2dfb5467f7b3477ab Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 16 Aug 2023 03:19:37 -0700 Subject: [PATCH 029/108] Use dependency management versions (#1002) --- dependencyManagement/build.gradle.kts | 1 + disk-buffering/build.gradle.kts | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 05ca18fc7..b2d96f9bd 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -40,6 +40,7 @@ val CORE_DEPENDENCIES = listOf( "io.prometheus:simpleclient_common:${prometheusVersion}", "io.prometheus:simpleclient_httpserver:${prometheusVersion}", "org.mockito:mockito-core:${mockitoVersion}", + "org.mockito:mockito-inline:${mockitoVersion}", "org.mockito:mockito-junit-jupiter:${mockitoVersion}", "org.slf4j:slf4j-api:${slf4jVersion}", "org.slf4j:slf4j-simple:${slf4jVersion}", diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 135cc3776..0ae73bc30 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -15,15 +15,14 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -val autovalueVersion = "1.10.3" dependencies { api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-exporter-otlp-common") implementation("io.opentelemetry.proto:opentelemetry-proto:0.20.0-alpha") - compileOnly("com.google.auto.value:auto-value-annotations:$autovalueVersion") - annotationProcessor("com.google.auto.value:auto-value:$autovalueVersion") + compileOnly("com.google.auto.value:auto-value-annotations") + annotationProcessor("com.google.auto.value:auto-value") signature("com.toasttab.android:gummy-bears-api-24:0.5.1@signature") - testImplementation("org.mockito:mockito-inline:4.11.0") + testImplementation("org.mockito:mockito-inline") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") } From 67ea05899bccbb7c72f842f60225e8064d7c3e85 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 16 Aug 2023 13:05:14 -0700 Subject: [PATCH 030/108] Remove unused plugin (#1004) --- build.gradle.kts | 1 - dependencyManagement/build.gradle.kts | 23 ----------------------- settings.gradle.kts | 1 - 3 files changed, 25 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2e02ae404..6e586f336 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,6 @@ plugins { id("idea") - id("com.github.ben-manes.versions") id("io.github.gradle-nexus.publish-plugin") } diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index b2d96f9bd..f21650b59 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -1,9 +1,5 @@ -import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask - plugins { `java-platform` - - id("com.github.ben-manes.versions") } data class DependencySet(val group: String, val version: String, val modules: List) @@ -85,22 +81,3 @@ dependencies { } } } - -fun isNonStable(version: String): Boolean { - val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) } - val regex = "^[0-9,.v-]+(-r)?$".toRegex() - val isGuava = version.endsWith("-jre") - val isStable = stableKeyword || regex.matches(version) || isGuava - return isStable.not() -} - -tasks { - named("dependencyUpdates") { - revision = "release" - checkConstraints = true - - rejectVersionIf { - isNonStable(candidate.version) - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index fa53c7376..8e312c449 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,5 @@ pluginManagement { plugins { - id("com.github.ben-manes.versions") version "0.47.0" id("com.github.johnrengelman.shadow") version "8.1.1" id("com.gradle.enterprise") version "3.14.1" id("io.github.gradle-nexus.publish-plugin") version "1.3.0" From c8917e4d2d216cdae2f909bd40864b26b09d3e73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 11:07:31 +0200 Subject: [PATCH 031/108] Update dependency io.opentelemetry.javaagent:opentelemetry-javaagent to v1.29.0 (#1006) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index f21650b59..f40536845 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -46,7 +46,7 @@ val CORE_DEPENDENCIES = listOf( ) val DEPENDENCIES = listOf( - "io.opentelemetry.javaagent:opentelemetry-javaagent:1.28.0", + "io.opentelemetry.javaagent:opentelemetry-javaagent:1.29.0", "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", From 87825466e78e6f1cd15297c8ef3a45fbdb1dedbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 09:14:49 +0000 Subject: [PATCH 032/108] Update dependency gradle to v8.3 (#1007) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 28216 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c2447881d..864d6c475 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionSha256Sum=591855b517fc635b9e04de1d05d5e76ada3f89f5fc76f87978d1b245b4f69225 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca14..0adc8e1a5 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum From 3af6cf32c1862c7b750ac1c2370da8912aeecc1d Mon Sep 17 00:00:00 2001 From: kes2464 Date: Sat, 19 Aug 2023 01:14:29 +1000 Subject: [PATCH 033/108] add a provider for consistent parent based probability sampler (#1005) --- consistent-sampling/build.gradle.kts | 1 + ...dConsistentProbabilitySamplerProvider.java | 25 +++++++++++++++++++ ...ure.spi.traces.ConfigurableSamplerProvider | 1 + 3 files changed, 27 insertions(+) create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ParentBasedConsistentProbabilitySamplerProvider.java create mode 100644 consistent-sampling/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index 5010e49b7..65f9fc25e 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -8,6 +8,7 @@ otelJava.moduleName.set("io.opentelemetry.contrib.sampler.consistent") dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") + api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") testImplementation("org.hipparchus:hipparchus-core:2.3") testImplementation("org.hipparchus:hipparchus-stat:2.3") } diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ParentBasedConsistentProbabilitySamplerProvider.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ParentBasedConsistentProbabilitySamplerProvider.java new file mode 100644 index 000000000..0ca7e17a9 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ParentBasedConsistentProbabilitySamplerProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; +import io.opentelemetry.sdk.trace.samplers.Sampler; + +public final class ParentBasedConsistentProbabilitySamplerProvider + implements ConfigurableSamplerProvider { + + @Override + public Sampler createSampler(ConfigProperties config) { + double samplingProbability = config.getDouble("otel.traces.sampler.arg", 1.0d); + return ConsistentSampler.parentBased(ConsistentSampler.probabilityBased(samplingProbability)); + } + + @Override + public String getName() { + return "parentbased_consistent_probability"; + } +} diff --git a/consistent-sampling/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider b/consistent-sampling/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider new file mode 100644 index 000000000..948fcc325 --- /dev/null +++ b/consistent-sampling/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider @@ -0,0 +1 @@ +io.opentelemetry.contrib.sampler.consistent.ParentBasedConsistentProbabilitySamplerProvider From be3aa3b157614760f743a4b4ce6f240cecafb85d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 23:18:26 +0000 Subject: [PATCH 034/108] Update dependency org.testcontainers:testcontainers-bom to v1.19.0 (#1010) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index f40536845..15c4f00f9 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -14,7 +14,7 @@ val DEPENDENCY_BOMS = listOf( "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.57.2", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", - "org.testcontainers:testcontainers-bom:1.18.3" + "org.testcontainers:testcontainers-bom:1.19.0" ) val autoServiceVersion = "1.1.1" From 30665f73d4ff9f6cbd8061c630ef8c4ae447c9bd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:21:22 +0200 Subject: [PATCH 035/108] Update dependency org.codehaus.groovy:groovy-bom to v3.0.19 (#1011) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- jmx-metrics/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jmx-metrics/build.gradle.kts b/jmx-metrics/build.gradle.kts index 42c8586e9..bccd25e1b 100644 --- a/jmx-metrics/build.gradle.kts +++ b/jmx-metrics/build.gradle.kts @@ -25,7 +25,7 @@ repositories { mavenLocal() } -val groovyVersion = "3.0.18" +val groovyVersion = "3.0.19" dependencies { api(platform("org.codehaus.groovy:groovy-bom:$groovyVersion")) From 863fb725e55a09e631dd9ae8407e5228a52360c2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 07:47:30 -0700 Subject: [PATCH 036/108] Update dependency com.linecorp.armeria:armeria-bom to v1.25.0 (#1012) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 15c4f00f9..1f59ca31c 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", "com.google.guava:guava-bom:32.1.2-jre", - "com.linecorp.armeria:armeria-bom:1.24.3", + "com.linecorp.armeria:armeria-bom:1.25.0", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.57.2", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", From ceb5a82d181465131f4f432e2d96e50d5d3a1d24 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 23 Aug 2023 09:14:49 -0700 Subject: [PATCH 037/108] Update change log (#1013) --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e5e738b9..cdcfc9ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ ## Unreleased +### Consistent sampling + +- Add a provider for consistent parent based probability sampler + ([#1005](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1005)) + +### Disk buffering + +- Migrate StorageFile to FileOperations + ([#986](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/986)) + +### JMX metrics + +- [jmx-metrics] Collect in callback + ([#949](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/949)) +- Added transformation closure to MBeanHelper + ([#960](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/960)) + ## Version 1.28.0 (2023-07-14) ### AWS X-Ray SDK support From 83060077495a97901aa3a66a5e428e815e191fb8 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:31:40 -0700 Subject: [PATCH 038/108] Update version to 1.30.0-SNAPSHOT (#1016) --- CHANGELOG.md | 2 ++ version.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcfc9ef5..f06aeb39f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## Version 1.29.0 (2023-08-23) + ### Consistent sampling - Add a provider for consistent parent based probability sampler diff --git a/version.gradle.kts b/version.gradle.kts index 7e23763e4..a428e3c21 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.29.0-SNAPSHOT" -val alphaVersion = "1.29.0-alpha-SNAPSHOT" +val stableVersion = "1.30.0-SNAPSHOT" +val alphaVersion = "1.30.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") { From 493f3c5b1afa040c848b2dc3854140dce00cbb03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 07:58:06 +0200 Subject: [PATCH 039/108] Update dependency com.linecorp.armeria:armeria-bom to v1.25.1 (#1019) --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 1f59ca31c..31d0642e5 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", "com.google.guava:guava-bom:32.1.2-jre", - "com.linecorp.armeria:armeria-bom:1.25.0", + "com.linecorp.armeria:armeria-bom:1.25.1", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.57.2", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", From 8bfad761875423537717d5441476ab1144b5ebe2 Mon Sep 17 00:00:00 2001 From: LikeTheSalad <56847527+LikeTheSalad@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:04:56 +0200 Subject: [PATCH 040/108] Removing protobuf dependency (#1008) Co-authored-by: Trask Stalnaker --- disk-buffering/build.gradle.kts | 30 +- .../mapping/common/AttributesMapper.java | 66 +-- .../common/BaseProtoSignalsDataMapper.java | 14 +- .../mapping/common/ByteStringMapper.java | 6 +- .../mapping/common/ResourceMapper.java | 8 +- .../mapping/logs/LogRecordDataMapper.java | 53 +-- .../mapping/logs/ProtoLogsDataMapper.java | 24 +- .../mapping/metrics/MetricDataMapper.java | 450 +++++++++--------- .../metrics/ProtoMetricsDataMapper.java | 24 +- .../mapping/spans/ProtoSpansDataMapper.java | 25 +- .../mapping/spans/SpanDataMapper.java | 112 ++--- .../serializers/LogRecordDataSerializer.java | 10 +- .../serializers/MetricDataSerializer.java | 10 +- .../serializers/SpanDataSerializer.java | 10 +- .../reader/DelimitedProtoStreamReader.java | 4 +- .../internal/utils/ProtobufTools.java | 51 ++ .../mapping/logs/ProtoLogsDataMapperTest.java | 34 +- .../metrics/ProtoMetricsDataMapperTest.java | 30 +- .../spans/ProtoSpansDataMapperTest.java | 30 +- 19 files changed, 532 insertions(+), 459 deletions(-) create mode 100644 disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/ProtobufTools.java diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 0ae73bc30..be2259dbb 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -5,6 +5,7 @@ plugins { id("otel.publish-conventions") id("me.champeau.jmh") version "0.7.1" id("ru.vyarus.animalsniffer") version "1.7.1" + id("com.squareup.wire") version "4.8.1" } description = "Exporter implementations that store signals on disk" @@ -17,8 +18,6 @@ java { dependencies { api("io.opentelemetry:opentelemetry-sdk") - implementation("io.opentelemetry:opentelemetry-exporter-otlp-common") - implementation("io.opentelemetry.proto:opentelemetry-proto:0.20.0-alpha") compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") signature("com.toasttab.android:gummy-bears-api-24:0.5.1@signature") @@ -47,3 +46,30 @@ jmh { timeOnIteration.set("5s") timeUnit.set("ms") } + +wire { + java {} + + sourcePath { + srcJar("io.opentelemetry.proto:opentelemetry-proto:0.20.0-alpha") + } + + root( + "opentelemetry.proto.trace.v1.TracesData", + "opentelemetry.proto.metrics.v1.MetricsData", + "opentelemetry.proto.logs.v1.LogsData", + ) +} + +// The javadoc from wire's generated classes has errors that make the task that generates the "javadoc" artifact to fail. This +// makes the javadoc task to ignore those generated classes. +tasks.withType(Javadoc::class.java) { + exclude("io/opentelemetry/proto/*") +} + +// The task that generates the "sources" artifact fails due to a "duplicated io/opentelemetry/proto/metrics/v1/Exemplar.java" file +// Which is strange since there's only one file like that which is generated by wire and the main "jar" task doesn't raise the same issue. +// This allows to ignore any subsequent files with the same path when creating the "sources" artifact. +tasks.named("sourcesJar", Jar::class.java) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapper.java index 8b4ceb05a..e017cb878 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapper.java @@ -32,15 +32,15 @@ public List attributesToProto(Attributes attributes) { public Attributes protoToAttributes(List values) { AttributesBuilder builder = Attributes.builder(); for (KeyValue keyValue : values) { - addValue(builder, keyValue.getKey(), keyValue.getValue()); + addValue(builder, keyValue.key, keyValue.value); } return builder.build(); } private static KeyValue attributeEntryToProto(AttributeKey key, Object value) { - KeyValue.Builder builder = KeyValue.newBuilder(); - builder.setKey(key.getKey()); - builder.setValue(attributeValueToProto(key.getType(), value)); + KeyValue.Builder builder = new KeyValue.Builder(); + builder.key(key.getKey()); + builder.value(attributeValueToProto(key.getType(), value)); return builder.build(); } @@ -68,37 +68,37 @@ private static AnyValue attributeValueToProto(AttributeType type, Object value) } private static AnyValue arrayToAnyValue(List value) { - return AnyValue.newBuilder() - .setArrayValue(ArrayValue.newBuilder().addAllValues(value).build()) + return new AnyValue.Builder() + .array_value(new ArrayValue.Builder().values(value).build()) .build(); } private static void addValue(AttributesBuilder builder, String key, AnyValue value) { - if (value.hasStringValue()) { - builder.put(AttributeKey.stringKey(key), value.getStringValue()); - } else if (value.hasBoolValue()) { - builder.put(AttributeKey.booleanKey(key), value.getBoolValue()); - } else if (value.hasIntValue()) { - builder.put(AttributeKey.longKey(key), value.getIntValue()); - } else if (value.hasDoubleValue()) { - builder.put(AttributeKey.doubleKey(key), value.getDoubleValue()); - } else if (value.hasArrayValue()) { - addArray(builder, key, value.getArrayValue()); + if (value.string_value != null) { + builder.put(AttributeKey.stringKey(key), value.string_value); + } else if (value.bool_value != null) { + builder.put(AttributeKey.booleanKey(key), value.bool_value); + } else if (value.int_value != null) { + builder.put(AttributeKey.longKey(key), value.int_value); + } else if (value.double_value != null) { + builder.put(AttributeKey.doubleKey(key), value.double_value); + } else if (value.array_value != null) { + addArray(builder, key, value.array_value); } else { throw new UnsupportedOperationException(); } } private static void addArray(AttributesBuilder builder, String key, ArrayValue arrayValue) { - List values = arrayValue.getValuesList(); + List values = arrayValue.values; AnyValue anyValue = values.get(0); - if (anyValue.hasStringValue()) { + if (anyValue.string_value != null) { builder.put(AttributeKey.stringArrayKey(key), anyValuesToStrings(values)); - } else if (anyValue.hasBoolValue()) { + } else if (anyValue.bool_value != null) { builder.put(AttributeKey.booleanArrayKey(key), anyValuesToBooleans(values)); - } else if (anyValue.hasIntValue()) { + } else if (anyValue.int_value != null) { builder.put(AttributeKey.longArrayKey(key), anyValuesToLongs(values)); - } else if (anyValue.hasDoubleValue()) { + } else if (anyValue.double_value != null) { builder.put(AttributeKey.doubleArrayKey(key), anyValuesToDoubles(values)); } else { throw new UnsupportedOperationException(); @@ -106,38 +106,38 @@ private static void addArray(AttributesBuilder builder, String key, ArrayValue a } private static AnyValue stringToAnyValue(String value) { - AnyValue.Builder anyValue = AnyValue.newBuilder(); + AnyValue.Builder anyValue = new AnyValue.Builder(); - anyValue.setStringValue(value); + anyValue.string_value(value); return anyValue.build(); } private static AnyValue booleanToAnyValue(Boolean value) { - AnyValue.Builder anyValue = AnyValue.newBuilder(); + AnyValue.Builder anyValue = new AnyValue.Builder(); if (value != null) { - anyValue.setBoolValue(value); + anyValue.bool_value(value); } return anyValue.build(); } private static AnyValue longToAnyValue(Long value) { - AnyValue.Builder anyValue = AnyValue.newBuilder(); + AnyValue.Builder anyValue = new AnyValue.Builder(); if (value != null) { - anyValue.setIntValue(value); + anyValue.int_value(value); } return anyValue.build(); } private static AnyValue doubleToAnyValue(Double value) { - AnyValue.Builder anyValue = AnyValue.newBuilder(); + AnyValue.Builder anyValue = new AnyValue.Builder(); if (value != null) { - anyValue.setDoubleValue(value); + anyValue.double_value(value); } return anyValue.build(); @@ -216,18 +216,18 @@ private static List anyValuesToDoubles(List values) { } private static String anyValueToString(AnyValue value) { - return value.getStringValue(); + return value.string_value; } private static Boolean anyValueToBoolean(AnyValue value) { - return value.getBoolValue(); + return value.bool_value; } private static Long anyValueToLong(AnyValue value) { - return value.getIntValue(); + return value.int_value; } private static Double anyValueToDouble(AnyValue value) { - return value.getDoubleValue(); + return value.double_value; } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/BaseProtoSignalsDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/BaseProtoSignalsDataMapper.java index ef263c53d..aff6ab560 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/BaseProtoSignalsDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/BaseProtoSignalsDataMapper.java @@ -76,10 +76,10 @@ protected Resource protoToResource( protected InstrumentationScopeInfo protoToInstrumentationScopeInfo( InstrumentationScope scope, @Nullable String schemaUrl) { - InstrumentationScopeInfoBuilder builder = InstrumentationScopeInfo.builder(scope.getName()); - builder.setAttributes(protoToAttributes(scope.getAttributesList())); - if (!scope.getVersion().isEmpty()) { - builder.setVersion(scope.getVersion()); + InstrumentationScopeInfoBuilder builder = InstrumentationScopeInfo.builder(scope.name); + builder.setAttributes(protoToAttributes(scope.attributes)); + if (!scope.version.isEmpty()) { + builder.setVersion(scope.version); } if (schemaUrl != null) { builder.setSchemaUrl(schemaUrl); @@ -89,11 +89,11 @@ protected InstrumentationScopeInfo protoToInstrumentationScopeInfo( protected InstrumentationScope instrumentationScopeToProto(InstrumentationScopeInfo source) { InstrumentationScope.Builder builder = - InstrumentationScope.newBuilder().setName(source.getName()); + new InstrumentationScope.Builder().name(source.getName()); if (source.getVersion() != null) { - builder.setVersion(source.getVersion()); + builder.version(source.getVersion()); } - builder.addAllAttributes(attributesToProto(source.getAttributes())); + builder.attributes.addAll(attributesToProto(source.getAttributes())); return builder.build(); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ByteStringMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ByteStringMapper.java index a04fbe0b7..ca8366e8a 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ByteStringMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ByteStringMapper.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.common; -import com.google.protobuf.ByteString; +import okio.ByteString; public final class ByteStringMapper { @@ -16,10 +16,10 @@ public static ByteStringMapper getInstance() { } public ByteString stringToProto(String source) { - return ByteString.copyFromUtf8(source); + return ByteString.encodeUtf8(source); } public String protoToString(ByteString source) { - return source.toStringUtf8(); + return source.utf8(); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapper.java index c93894cb6..702202443 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapper.java @@ -18,9 +18,8 @@ public static ResourceMapper getInstance() { } public Resource mapToProto(io.opentelemetry.sdk.resources.Resource sdkResource) { - return Resource.newBuilder() - .addAllAttributes( - AttributesMapper.getInstance().attributesToProto(sdkResource.getAttributes())) + return new Resource.Builder() + .attributes(AttributesMapper.getInstance().attributesToProto(sdkResource.getAttributes())) .build(); } @@ -31,8 +30,7 @@ public io.opentelemetry.sdk.resources.Resource mapToSdk( if (schemaUrl != null) { resource.setSchemaUrl(schemaUrl); } - resource.putAll( - AttributesMapper.getInstance().protoToAttributes(protoResource.getAttributesList())); + resource.putAll(AttributesMapper.getInstance().protoToAttributes(protoResource.attributes)); return resource.build(); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapper.java index 8cedb2d4e..92af6a387 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapper.java @@ -30,21 +30,21 @@ public static LogRecordDataMapper getInstance() { } public LogRecord mapToProto(LogRecordData source) { - LogRecord.Builder logRecord = LogRecord.newBuilder(); + LogRecord.Builder logRecord = new LogRecord.Builder(); - logRecord.setTimeUnixNano(source.getTimestampEpochNanos()); - logRecord.setObservedTimeUnixNano(source.getObservedTimestampEpochNanos()); + logRecord.time_unix_nano(source.getTimestampEpochNanos()); + logRecord.observed_time_unix_nano(source.getObservedTimestampEpochNanos()); if (source.getSeverity() != null) { - logRecord.setSeverityNumber(severityToProto(source.getSeverity())); + logRecord.severity_number(severityToProto(source.getSeverity())); } if (source.getSeverityText() != null) { - logRecord.setSeverityText(source.getSeverityText()); + logRecord.severity_text(source.getSeverityText()); } if (source.getBody() != null) { - logRecord.setBody(bodyToAnyValue(source.getBody())); + logRecord.body(bodyToAnyValue(source.getBody())); } - logRecord.setFlags(source.getSpanContext().getTraceFlags().asByte()); + logRecord.flags(source.getSpanContext().getTraceFlags().asByte()); addExtrasToProtoBuilder(source, logRecord); @@ -52,12 +52,12 @@ public LogRecord mapToProto(LogRecordData source) { } private static void addExtrasToProtoBuilder(LogRecordData source, LogRecord.Builder target) { - target.addAllAttributes( + target.attributes.addAll( AttributesMapper.getInstance().attributesToProto(source.getAttributes())); SpanContext spanContext = source.getSpanContext(); - target.setSpanId(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); - target.setTraceId(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); - target.setDroppedAttributesCount( + target.span_id(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); + target.trace_id(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); + target.dropped_attributes_count( source.getTotalAttributeCount() - source.getAttributes().size()); } @@ -65,12 +65,12 @@ public LogRecordData mapToSdk( LogRecord source, Resource resource, InstrumentationScopeInfo scopeInfo) { LogRecordDataImpl.Builder logRecordData = LogRecordDataImpl.builder(); - logRecordData.setTimestampEpochNanos(source.getTimeUnixNano()); - logRecordData.setObservedTimestampEpochNanos(source.getObservedTimeUnixNano()); - logRecordData.setSeverity(severityNumberToSdk(source.getSeverityNumber())); - logRecordData.setSeverityText(source.getSeverityText()); - if (source.hasBody()) { - logRecordData.setBody(anyValueToBody(source.getBody())); + logRecordData.setTimestampEpochNanos(source.time_unix_nano); + logRecordData.setObservedTimestampEpochNanos(source.observed_time_unix_nano); + logRecordData.setSeverity(severityNumberToSdk(source.severity_number)); + logRecordData.setSeverityText(source.severity_text); + if (source.body != null) { + logRecordData.setBody(anyValueToBody(source.body)); } addExtrasToSdkItemBuilder(source, logRecordData, resource, scopeInfo); @@ -83,31 +83,30 @@ private static void addExtrasToSdkItemBuilder( LogRecordDataImpl.Builder target, Resource resource, InstrumentationScopeInfo scopeInfo) { - Attributes attributes = - AttributesMapper.getInstance().protoToAttributes(source.getAttributesList()); + Attributes attributes = AttributesMapper.getInstance().protoToAttributes(source.attributes); target.setAttributes(attributes); target.setSpanContext( SpanContext.create( - ByteStringMapper.getInstance().protoToString(source.getTraceId()), - ByteStringMapper.getInstance().protoToString(source.getSpanId()), + ByteStringMapper.getInstance().protoToString(source.trace_id), + ByteStringMapper.getInstance().protoToString(source.span_id), TraceFlags.getSampled(), TraceState.getDefault())); - target.setTotalAttributeCount(source.getDroppedAttributesCount() + attributes.size()); + target.setTotalAttributeCount(source.dropped_attributes_count + attributes.size()); target.setResource(resource); target.setInstrumentationScopeInfo(scopeInfo); } private static AnyValue bodyToAnyValue(Body body) { - return AnyValue.newBuilder().setStringValue(body.asString()).build(); + return new AnyValue.Builder().string_value(body.asString()).build(); } private static SeverityNumber severityToProto(Severity severity) { - return SeverityNumber.forNumber(severity.getSeverityNumber()); + return SeverityNumber.fromValue(severity.getSeverityNumber()); } private static Body anyValueToBody(AnyValue source) { - if (source.hasStringValue()) { - return Body.string(source.getStringValue()); + if (source.string_value != null) { + return Body.string(source.string_value); } else { return Body.empty(); } @@ -115,7 +114,7 @@ private static Body anyValueToBody(AnyValue source) { private static Severity severityNumberToSdk(SeverityNumber source) { for (Severity value : Severity.values()) { - if (value.getSeverityNumber() == source.getNumber()) { + if (value.getSeverityNumber() == source.getValue()) { return value; } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapper.java index 5fbaa62b7..1d11c177f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapper.java @@ -40,7 +40,7 @@ protected LogRecordData protoToSignalItem( @Override protected List getProtoResources(LogsData logsData) { - return logsData.getResourceLogsList(); + return logsData.resource_logs; } @Override @@ -53,49 +53,49 @@ protected LogsData createProtoData( for (Map.Entry> logsByScope : instrumentationScopeInfoScopedLogsMap.entrySet()) { ScopeLogs.Builder scopeBuilder = createProtoScopeBuilder(logsByScope.getKey()); - scopeBuilder.addAllLogRecords(logsByScope.getValue()); - resourceLogsBuilder.addScopeLogs(scopeBuilder.build()); + scopeBuilder.log_records.addAll(logsByScope.getValue()); + resourceLogsBuilder.scope_logs.add(scopeBuilder.build()); } items.add(resourceLogsBuilder.build()); }); - return LogsData.newBuilder().addAllResourceLogs(items).build(); + return new LogsData.Builder().resource_logs(items).build(); } private ScopeLogs.Builder createProtoScopeBuilder(InstrumentationScopeInfo scopeInfo) { ScopeLogs.Builder builder = - ScopeLogs.newBuilder().setScope(instrumentationScopeToProto(scopeInfo)); + new ScopeLogs.Builder().scope(instrumentationScopeToProto(scopeInfo)); if (scopeInfo.getSchemaUrl() != null) { - builder.setSchemaUrl(scopeInfo.getSchemaUrl()); + builder.schema_url(scopeInfo.getSchemaUrl()); } return builder; } private ResourceLogs.Builder createProtoResourceBuilder(Resource resource) { - ResourceLogs.Builder builder = ResourceLogs.newBuilder().setResource(resourceToProto(resource)); + ResourceLogs.Builder builder = new ResourceLogs.Builder().resource(resourceToProto(resource)); if (resource.getSchemaUrl() != null) { - builder.setSchemaUrl(resource.getSchemaUrl()); + builder.schema_url(resource.getSchemaUrl()); } return builder; } @Override protected List getSignalsFromProto(ScopeLogs scopeSignals) { - return scopeSignals.getLogRecordsList(); + return scopeSignals.log_records; } @Override protected InstrumentationScopeInfo getInstrumentationScopeFromProto(ScopeLogs scopeSignals) { - return protoToInstrumentationScopeInfo(scopeSignals.getScope(), scopeSignals.getSchemaUrl()); + return protoToInstrumentationScopeInfo(scopeSignals.scope, scopeSignals.schema_url); } @Override protected List getScopes(ResourceLogs resourceSignal) { - return resourceSignal.getScopeLogsList(); + return resourceSignal.scope_logs; } @Override protected Resource getResourceFromProto(ResourceLogs resourceSignal) { - return protoToResource(resourceSignal.getResource(), resourceSignal.getSchemaUrl()); + return protoToResource(resourceSignal.resource, resourceSignal.schema_url); } @Override diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapper.java index 512cc71cb..12df0d3e7 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapper.java @@ -72,11 +72,11 @@ public static MetricDataMapper getInstance() { } public Metric mapToProto(MetricData source) { - Metric.Builder metric = Metric.newBuilder(); + Metric.Builder metric = new Metric.Builder(); - metric.setName(source.getName()); - metric.setDescription(source.getDescription()); - metric.setUnit(source.getUnit()); + metric.name(source.getName()); + metric.description(source.getDescription()); + metric.unit(source.getUnit()); addDataToProto(source, metric); @@ -85,71 +85,70 @@ public Metric mapToProto(MetricData source) { @SuppressWarnings("unchecked") public MetricData mapToSdk(Metric source, Resource resource, InstrumentationScopeInfo scope) { - switch (source.getDataCase()) { - case GAUGE: - DataWithType gaugeDataWithType = mapGaugeToSdk(source.getGauge()); - if (gaugeDataWithType.type == MetricDataType.DOUBLE_GAUGE) { - return ImmutableMetricData.createDoubleGauge( - resource, - scope, - source.getName(), - source.getDescription(), - source.getUnit(), - (GaugeData) gaugeDataWithType.data); - } else { - return ImmutableMetricData.createLongGauge( - resource, - scope, - source.getName(), - source.getDescription(), - source.getUnit(), - (GaugeData) gaugeDataWithType.data); - } - case SUM: - DataWithType sumDataWithType = mapSumToSdk(source.getSum()); - if (sumDataWithType.type == MetricDataType.DOUBLE_SUM) { - return ImmutableMetricData.createDoubleSum( - resource, - scope, - source.getName(), - source.getDescription(), - source.getUnit(), - (SumData) sumDataWithType.data); - } else { - return ImmutableMetricData.createLongSum( - resource, - scope, - source.getName(), - source.getDescription(), - source.getUnit(), - (SumData) sumDataWithType.data); - } - case SUMMARY: - return ImmutableMetricData.createDoubleSummary( + if (source.gauge != null) { + DataWithType gaugeDataWithType = mapGaugeToSdk(source.gauge); + if (gaugeDataWithType.type == MetricDataType.DOUBLE_GAUGE) { + return ImmutableMetricData.createDoubleGauge( resource, scope, - source.getName(), - source.getDescription(), - source.getUnit(), - mapSummaryToSdk(source.getSummary())); - case HISTOGRAM: - return ImmutableMetricData.createDoubleHistogram( + source.name, + source.description, + source.unit, + (GaugeData) gaugeDataWithType.data); + } else { + return ImmutableMetricData.createLongGauge( resource, scope, - source.getName(), - source.getDescription(), - source.getUnit(), - mapHistogramToSdk(source.getHistogram())); - case EXPONENTIAL_HISTOGRAM: - return ImmutableMetricData.createExponentialHistogram( + source.name, + source.description, + source.unit, + (GaugeData) gaugeDataWithType.data); + } + } else if (source.sum != null) { + DataWithType sumDataWithType = mapSumToSdk(source.sum); + if (sumDataWithType.type == MetricDataType.DOUBLE_SUM) { + return ImmutableMetricData.createDoubleSum( resource, scope, - source.getName(), - source.getDescription(), - source.getUnit(), - mapExponentialHistogramToSdk(source.getExponentialHistogram())); - default: - throw new UnsupportedOperationException(); + source.name, + source.description, + source.unit, + (SumData) sumDataWithType.data); + } else { + return ImmutableMetricData.createLongSum( + resource, + scope, + source.name, + source.description, + source.unit, + (SumData) sumDataWithType.data); + } + } else if (source.summary != null) { + return ImmutableMetricData.createDoubleSummary( + resource, + scope, + source.name, + source.description, + source.unit, + mapSummaryToSdk(source.summary)); + } else if (source.histogram != null) { + return ImmutableMetricData.createDoubleHistogram( + resource, + scope, + source.name, + source.description, + source.unit, + mapHistogramToSdk(source.histogram)); + } else if (source.exponential_histogram != null) { + return ImmutableMetricData.createExponentialHistogram( + resource, + scope, + source.name, + source.description, + source.unit, + mapExponentialHistogramToSdk(source.exponential_histogram)); + } else { + throw new UnsupportedOperationException(); } } @@ -157,36 +156,36 @@ public MetricData mapToSdk(Metric source, Resource resource, InstrumentationScop private static void addDataToProto(MetricData source, Metric.Builder target) { switch (source.getType()) { case LONG_GAUGE: - target.setGauge(mapLongGaugeToProto((GaugeData) source.getData())); + target.gauge(mapLongGaugeToProto((GaugeData) source.getData())); break; case DOUBLE_GAUGE: - target.setGauge(mapDoubleGaugeToProto((GaugeData) source.getData())); + target.gauge(mapDoubleGaugeToProto((GaugeData) source.getData())); break; case LONG_SUM: - target.setSum(mapLongSumToProto((SumData) source.getData())); + target.sum(mapLongSumToProto((SumData) source.getData())); break; case DOUBLE_SUM: - target.setSum(mapDoubleSumToProto((SumData) source.getData())); + target.sum(mapDoubleSumToProto((SumData) source.getData())); break; case SUMMARY: - target.setSummary(mapSummaryToProto((SummaryData) source.getData())); + target.summary(mapSummaryToProto((SummaryData) source.getData())); break; case HISTOGRAM: - target.setHistogram(mapHistogramToProto((HistogramData) source.getData())); + target.histogram(mapHistogramToProto((HistogramData) source.getData())); break; case EXPONENTIAL_HISTOGRAM: - target.setExponentialHistogram( + target.exponential_histogram( mapExponentialHistogramToProto((ExponentialHistogramData) source.getData())); break; } } private static DataWithType mapGaugeToSdk(Gauge gauge) { - if (gauge.getDataPointsCount() > 0) { - NumberDataPoint dataPoint = gauge.getDataPoints(0); - if (dataPoint.hasAsInt()) { + if (!gauge.data_points.isEmpty()) { + NumberDataPoint dataPoint = gauge.data_points.get(0); + if (dataPoint.as_int != null) { return new DataWithType(mapLongGaugeToSdk(gauge), MetricDataType.LONG_GAUGE); - } else if (dataPoint.hasAsDouble()) { + } else if (dataPoint.as_double != null) { return new DataWithType(mapDoubleGaugeToSdk(gauge), MetricDataType.DOUBLE_GAUGE); } } @@ -194,11 +193,11 @@ private static DataWithType mapGaugeToSdk(Gauge gauge) { } private static DataWithType mapSumToSdk(Sum sum) { - if (sum.getDataPointsCount() > 0) { - NumberDataPoint dataPoint = sum.getDataPoints(0); - if (dataPoint.hasAsInt()) { + if (!sum.data_points.isEmpty()) { + NumberDataPoint dataPoint = sum.data_points.get(0); + if (dataPoint.as_int != null) { return new DataWithType(mapLongSumToSdk(sum), MetricDataType.LONG_SUM); - } else if (dataPoint.hasAsDouble()) { + } else if (dataPoint.as_double != null) { return new DataWithType(mapDoubleSumToSdk(sum), MetricDataType.DOUBLE_SUM); } } @@ -206,11 +205,11 @@ private static DataWithType mapSumToSdk(Sum sum) { } private static Gauge mapLongGaugeToProto(GaugeData data) { - Gauge.Builder gauge = Gauge.newBuilder(); + Gauge.Builder gauge = new Gauge.Builder(); if (data.getPoints() != null) { for (LongPointData point : data.getPoints()) { - gauge.addDataPoints(longPointDataToNumberDataPoint(point)); + gauge.data_points.add(longPointDataToNumberDataPoint(point)); } } @@ -218,11 +217,11 @@ private static Gauge mapLongGaugeToProto(GaugeData data) { } private static Gauge mapDoubleGaugeToProto(GaugeData data) { - Gauge.Builder gauge = Gauge.newBuilder(); + Gauge.Builder gauge = new Gauge.Builder(); if (data.getPoints() != null) { for (DoublePointData point : data.getPoints()) { - gauge.addDataPoints(doublePointDataToNumberDataPoint(point)); + gauge.data_points.add(doublePointDataToNumberDataPoint(point)); } } @@ -230,41 +229,39 @@ private static Gauge mapDoubleGaugeToProto(GaugeData data) { } private static Sum mapLongSumToProto(SumData data) { - Sum.Builder sum = Sum.newBuilder(); + Sum.Builder sum = new Sum.Builder(); if (data.getPoints() != null) { for (LongPointData point : data.getPoints()) { - sum.addDataPoints(longPointDataToNumberDataPoint(point)); + sum.data_points.add(longPointDataToNumberDataPoint(point)); } } - sum.setIsMonotonic(data.isMonotonic()); - sum.setAggregationTemporality( - mapAggregationTemporalityToProto(data.getAggregationTemporality())); + sum.is_monotonic(data.isMonotonic()); + sum.aggregation_temporality(mapAggregationTemporalityToProto(data.getAggregationTemporality())); return sum.build(); } private static Sum mapDoubleSumToProto(SumData data) { - Sum.Builder sum = Sum.newBuilder(); + Sum.Builder sum = new Sum.Builder(); if (data.getPoints() != null) { for (DoublePointData point : data.getPoints()) { - sum.addDataPoints(doublePointDataToNumberDataPoint(point)); + sum.data_points.add(doublePointDataToNumberDataPoint(point)); } } - sum.setIsMonotonic(data.isMonotonic()); - sum.setAggregationTemporality( - mapAggregationTemporalityToProto(data.getAggregationTemporality())); + sum.is_monotonic(data.isMonotonic()); + sum.aggregation_temporality(mapAggregationTemporalityToProto(data.getAggregationTemporality())); return sum.build(); } private static Summary mapSummaryToProto(SummaryData data) { - Summary.Builder summary = Summary.newBuilder(); + Summary.Builder summary = new Summary.Builder(); if (data.getPoints() != null) { for (SummaryPointData point : data.getPoints()) { - summary.addDataPoints(summaryPointDataToSummaryDataPoint(point)); + summary.data_points.add(summaryPointDataToSummaryDataPoint(point)); } } @@ -272,14 +269,14 @@ private static Summary mapSummaryToProto(SummaryData data) { } private static Histogram mapHistogramToProto(HistogramData data) { - Histogram.Builder histogram = Histogram.newBuilder(); + Histogram.Builder histogram = new Histogram.Builder(); if (data.getPoints() != null) { for (HistogramPointData point : data.getPoints()) { - histogram.addDataPoints(histogramPointDataToHistogramDataPoint(point)); + histogram.data_points.add(histogramPointDataToHistogramDataPoint(point)); } } - histogram.setAggregationTemporality( + histogram.aggregation_temporality( mapAggregationTemporalityToProto(data.getAggregationTemporality())); return histogram.build(); @@ -287,29 +284,29 @@ private static Histogram mapHistogramToProto(HistogramData data) { private static ExponentialHistogram mapExponentialHistogramToProto( ExponentialHistogramData data) { - ExponentialHistogram.Builder exponentialHistogram = ExponentialHistogram.newBuilder(); + ExponentialHistogram.Builder exponentialHistogram = new ExponentialHistogram.Builder(); if (data.getPoints() != null) { for (ExponentialHistogramPointData point : data.getPoints()) { - exponentialHistogram.addDataPoints( + exponentialHistogram.data_points.add( exponentialHistogramPointDataToExponentialHistogramDataPoint(point)); } } - exponentialHistogram.setAggregationTemporality( + exponentialHistogram.aggregation_temporality( mapAggregationTemporalityToProto(data.getAggregationTemporality())); return exponentialHistogram.build(); } private static NumberDataPoint longPointDataToNumberDataPoint(LongPointData source) { - NumberDataPoint.Builder numberDataPoint = NumberDataPoint.newBuilder(); + NumberDataPoint.Builder numberDataPoint = new NumberDataPoint.Builder(); - numberDataPoint.setStartTimeUnixNano(source.getStartEpochNanos()); - numberDataPoint.setTimeUnixNano(source.getEpochNanos()); - numberDataPoint.setAsInt(source.getValue()); + numberDataPoint.start_time_unix_nano(source.getStartEpochNanos()); + numberDataPoint.time_unix_nano(source.getEpochNanos()); + numberDataPoint.as_int(source.getValue()); if (source.getExemplars() != null) { for (LongExemplarData exemplar : source.getExemplars()) { - numberDataPoint.addExemplars(longExemplarDataToExemplar(exemplar)); + numberDataPoint.exemplars.add(longExemplarDataToExemplar(exemplar)); } } @@ -320,18 +317,18 @@ private static NumberDataPoint longPointDataToNumberDataPoint(LongPointData sour private static void addAttributesToNumberDataPoint( PointData source, NumberDataPoint.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); + target.attributes.addAll(attributesToProto(source.getAttributes())); } private static NumberDataPoint doublePointDataToNumberDataPoint(DoublePointData source) { - NumberDataPoint.Builder numberDataPoint = NumberDataPoint.newBuilder(); + NumberDataPoint.Builder numberDataPoint = new NumberDataPoint.Builder(); - numberDataPoint.setStartTimeUnixNano(source.getStartEpochNanos()); - numberDataPoint.setTimeUnixNano(source.getEpochNanos()); - numberDataPoint.setAsDouble(source.getValue()); + numberDataPoint.start_time_unix_nano(source.getStartEpochNanos()); + numberDataPoint.time_unix_nano(source.getEpochNanos()); + numberDataPoint.as_double(source.getValue()); if (source.getExemplars() != null) { for (DoubleExemplarData exemplar : source.getExemplars()) { - numberDataPoint.addExemplars(doubleExemplarDataToExemplar(exemplar)); + numberDataPoint.exemplars.add(doubleExemplarDataToExemplar(exemplar)); } } @@ -342,17 +339,17 @@ private static NumberDataPoint doublePointDataToNumberDataPoint(DoublePointData private static SummaryDataPoint summaryPointDataToSummaryDataPoint( SummaryPointData summaryPointData) { - SummaryDataPoint.Builder summaryDataPoint = SummaryDataPoint.newBuilder(); + SummaryDataPoint.Builder summaryDataPoint = new SummaryDataPoint.Builder(); - summaryDataPoint.setStartTimeUnixNano(summaryPointData.getStartEpochNanos()); - summaryDataPoint.setTimeUnixNano(summaryPointData.getEpochNanos()); + summaryDataPoint.start_time_unix_nano(summaryPointData.getStartEpochNanos()); + summaryDataPoint.time_unix_nano(summaryPointData.getEpochNanos()); if (summaryPointData.getValues() != null) { for (ValueAtQuantile value : summaryPointData.getValues()) { - summaryDataPoint.addQuantileValues(valueAtQuantileToValueAtQuantile(value)); + summaryDataPoint.quantile_values.add(valueAtQuantileToValueAtQuantile(value)); } } - summaryDataPoint.setCount(summaryPointData.getCount()); - summaryDataPoint.setSum(summaryPointData.getSum()); + summaryDataPoint.count(summaryPointData.getCount()); + summaryDataPoint.sum(summaryPointData.getSum()); addAttributesToSummaryDataPoint(summaryPointData, summaryDataPoint); @@ -361,37 +358,33 @@ private static SummaryDataPoint summaryPointDataToSummaryDataPoint( private static void addAttributesToSummaryDataPoint( PointData source, SummaryDataPoint.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); + target.attributes.addAll(attributesToProto(source.getAttributes())); } private static HistogramDataPoint histogramPointDataToHistogramDataPoint( HistogramPointData histogramPointData) { - HistogramDataPoint.Builder histogramDataPoint = HistogramDataPoint.newBuilder(); + HistogramDataPoint.Builder histogramDataPoint = new HistogramDataPoint.Builder(); - histogramDataPoint.setStartTimeUnixNano(histogramPointData.getStartEpochNanos()); - histogramDataPoint.setTimeUnixNano(histogramPointData.getEpochNanos()); + histogramDataPoint.start_time_unix_nano(histogramPointData.getStartEpochNanos()); + histogramDataPoint.time_unix_nano(histogramPointData.getEpochNanos()); if (histogramPointData.getCounts() != null) { - for (Long count : histogramPointData.getCounts()) { - histogramDataPoint.addBucketCounts(count); - } + histogramDataPoint.bucket_counts.addAll(histogramPointData.getCounts()); } if (histogramPointData.getBoundaries() != null) { - for (Double boundary : histogramPointData.getBoundaries()) { - histogramDataPoint.addExplicitBounds(boundary); - } + histogramDataPoint.explicit_bounds.addAll(histogramPointData.getBoundaries()); } if (histogramPointData.getExemplars() != null) { for (DoubleExemplarData exemplar : histogramPointData.getExemplars()) { - histogramDataPoint.addExemplars(doubleExemplarDataToExemplar(exemplar)); + histogramDataPoint.exemplars.add(doubleExemplarDataToExemplar(exemplar)); } } - histogramDataPoint.setCount(histogramPointData.getCount()); - histogramDataPoint.setSum(histogramPointData.getSum()); + histogramDataPoint.count(histogramPointData.getCount()); + histogramDataPoint.sum(histogramPointData.getSum()); if (histogramPointData.hasMin()) { - histogramDataPoint.setMin(histogramPointData.getMin()); + histogramDataPoint.min(histogramPointData.getMin()); } if (histogramPointData.hasMax()) { - histogramDataPoint.setMax(histogramPointData.getMax()); + histogramDataPoint.max(histogramPointData.getMax()); } addAttributesToHistogramDataPoint(histogramPointData, histogramDataPoint); @@ -401,36 +394,36 @@ private static HistogramDataPoint histogramPointDataToHistogramDataPoint( private static void addAttributesToHistogramDataPoint( HistogramPointData source, HistogramDataPoint.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); + target.attributes.addAll(attributesToProto(source.getAttributes())); } private static ExponentialHistogramDataPoint exponentialHistogramPointDataToExponentialHistogramDataPoint( ExponentialHistogramPointData exponentialHistogramPointData) { ExponentialHistogramDataPoint.Builder exponentialHistogramDataPoint = - ExponentialHistogramDataPoint.newBuilder(); + new ExponentialHistogramDataPoint.Builder(); - exponentialHistogramDataPoint.setStartTimeUnixNano( + exponentialHistogramDataPoint.start_time_unix_nano( exponentialHistogramPointData.getStartEpochNanos()); - exponentialHistogramDataPoint.setTimeUnixNano(exponentialHistogramPointData.getEpochNanos()); - exponentialHistogramDataPoint.setPositive( + exponentialHistogramDataPoint.time_unix_nano(exponentialHistogramPointData.getEpochNanos()); + exponentialHistogramDataPoint.positive( exponentialHistogramBucketsToBuckets(exponentialHistogramPointData.getPositiveBuckets())); - exponentialHistogramDataPoint.setNegative( + exponentialHistogramDataPoint.negative( exponentialHistogramBucketsToBuckets(exponentialHistogramPointData.getNegativeBuckets())); if (exponentialHistogramPointData.getExemplars() != null) { for (DoubleExemplarData exemplar : exponentialHistogramPointData.getExemplars()) { - exponentialHistogramDataPoint.addExemplars(doubleExemplarDataToExemplar(exemplar)); + exponentialHistogramDataPoint.exemplars.add(doubleExemplarDataToExemplar(exemplar)); } } - exponentialHistogramDataPoint.setCount(exponentialHistogramPointData.getCount()); - exponentialHistogramDataPoint.setSum(exponentialHistogramPointData.getSum()); - exponentialHistogramDataPoint.setScale(exponentialHistogramPointData.getScale()); - exponentialHistogramDataPoint.setZeroCount(exponentialHistogramPointData.getZeroCount()); + exponentialHistogramDataPoint.count(exponentialHistogramPointData.getCount()); + exponentialHistogramDataPoint.sum(exponentialHistogramPointData.getSum()); + exponentialHistogramDataPoint.scale(exponentialHistogramPointData.getScale()); + exponentialHistogramDataPoint.zero_count(exponentialHistogramPointData.getZeroCount()); if (exponentialHistogramPointData.hasMin()) { - exponentialHistogramDataPoint.setMin(exponentialHistogramPointData.getMin()); + exponentialHistogramDataPoint.min(exponentialHistogramPointData.getMin()); } if (exponentialHistogramPointData.hasMax()) { - exponentialHistogramDataPoint.setMax(exponentialHistogramPointData.getMax()); + exponentialHistogramDataPoint.max(exponentialHistogramPointData.getMax()); } addAttributesToExponentialHistogramDataPoint( @@ -441,29 +434,27 @@ private static void addAttributesToHistogramDataPoint( private static void addAttributesToExponentialHistogramDataPoint( ExponentialHistogramPointData source, ExponentialHistogramDataPoint.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); + target.attributes.addAll(attributesToProto(source.getAttributes())); } private static ExponentialHistogramDataPoint.Buckets exponentialHistogramBucketsToBuckets( ExponentialHistogramBuckets source) { ExponentialHistogramDataPoint.Buckets.Builder buckets = - ExponentialHistogramDataPoint.Buckets.newBuilder(); + new ExponentialHistogramDataPoint.Buckets.Builder(); if (source.getBucketCounts() != null) { - for (Long bucketCount : source.getBucketCounts()) { - buckets.addBucketCounts(bucketCount); - } + buckets.bucket_counts.addAll(source.getBucketCounts()); } - buckets.setOffset(source.getOffset()); + buckets.offset(source.getOffset()); return buckets.build(); } private static Exemplar doubleExemplarDataToExemplar(DoubleExemplarData doubleExemplarData) { - Exemplar.Builder exemplar = Exemplar.newBuilder(); + Exemplar.Builder exemplar = new Exemplar.Builder(); - exemplar.setTimeUnixNano(doubleExemplarData.getEpochNanos()); - exemplar.setAsDouble(doubleExemplarData.getValue()); + exemplar.time_unix_nano(doubleExemplarData.getEpochNanos()); + exemplar.as_double(doubleExemplarData.getValue()); addExtrasToExemplar(doubleExemplarData, exemplar); @@ -471,10 +462,10 @@ private static Exemplar doubleExemplarDataToExemplar(DoubleExemplarData doubleEx } private static Exemplar longExemplarDataToExemplar(LongExemplarData doubleExemplarData) { - Exemplar.Builder exemplar = Exemplar.newBuilder(); + Exemplar.Builder exemplar = new Exemplar.Builder(); - exemplar.setTimeUnixNano(doubleExemplarData.getEpochNanos()); - exemplar.setAsInt(doubleExemplarData.getValue()); + exemplar.time_unix_nano(doubleExemplarData.getEpochNanos()); + exemplar.as_int(doubleExemplarData.getValue()); addExtrasToExemplar(doubleExemplarData, exemplar); @@ -482,10 +473,10 @@ private static Exemplar longExemplarDataToExemplar(LongExemplarData doubleExempl } private static void addExtrasToExemplar(ExemplarData source, Exemplar.Builder target) { - target.addAllFilteredAttributes(attributesToProto(source.getFilteredAttributes())); + target.filtered_attributes.addAll(attributesToProto(source.getFilteredAttributes())); SpanContext spanContext = source.getSpanContext(); - target.setSpanId(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); - target.setTraceId(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); + target.span_id(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); + target.trace_id(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); } private static AggregationTemporality mapAggregationTemporalityToProto( @@ -500,7 +491,7 @@ private static AggregationTemporality mapAggregationTemporalityToProto( aggregationTemporality = AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE; break; default: - aggregationTemporality = AggregationTemporality.UNRECOGNIZED; + aggregationTemporality = AggregationTemporality.AGGREGATION_TEMPORALITY_UNSPECIFIED; } return aggregationTemporality; @@ -508,95 +499,99 @@ private static AggregationTemporality mapAggregationTemporalityToProto( private static SummaryData mapSummaryToSdk(Summary summary) { return ImmutableSummaryData.create( - summaryDataPointListToSummaryPointDataCollection(summary.getDataPointsList())); + summaryDataPointListToSummaryPointDataCollection(summary.data_points)); } private static HistogramData mapHistogramToSdk(Histogram histogram) { return ImmutableHistogramData.create( - mapAggregationTemporalityToSdk(histogram.getAggregationTemporality()), - histogramDataPointListToHistogramPointDataCollection(histogram.getDataPointsList())); + mapAggregationTemporalityToSdk(histogram.aggregation_temporality), + histogramDataPointListToHistogramPointDataCollection(histogram.data_points)); } private static ExponentialHistogramData mapExponentialHistogramToSdk( ExponentialHistogram source) { return ImmutableExponentialHistogramData.create( - mapAggregationTemporalityToSdk(source.getAggregationTemporality()), + mapAggregationTemporalityToSdk(source.aggregation_temporality), exponentialHistogramDataPointListToExponentialHistogramPointDataCollection( - source.getDataPointsList())); + source.data_points)); } private static ExponentialHistogramPointData exponentialHistogramDataPointToExponentialHistogramPointData( ExponentialHistogramDataPoint source) { + double min = (source.min != null) ? source.min : 0; + double max = (source.max != null) ? source.max : 0; return ImmutableExponentialHistogramPointData.create( - source.getScale(), - source.getSum(), - source.getZeroCount(), - source.hasMin(), - source.getMin(), - source.hasMax(), - source.getMax(), - mapBucketsFromProto(source.getPositive(), source.getScale()), - mapBucketsFromProto(source.getNegative(), source.getScale()), - source.getStartTimeUnixNano(), - source.getTimeUnixNano(), - protoToAttributes(source.getAttributesList()), - exemplarListToDoubleExemplarDataList(source.getExemplarsList())); + source.scale, + source.sum, + source.zero_count, + min > 0, + min, + max > 0, + max, + mapBucketsFromProto(source.positive, source.scale), + mapBucketsFromProto(source.negative, source.scale), + source.start_time_unix_nano, + source.time_unix_nano, + protoToAttributes(source.attributes), + exemplarListToDoubleExemplarDataList(source.exemplars)); } private static HistogramPointData histogramDataPointToHistogramPointData( HistogramDataPoint source) { + double min = (source.min != null) ? source.min : 0; + double max = (source.max != null) ? source.max : 0; return ImmutableHistogramPointData.create( - source.getStartTimeUnixNano(), - source.getTimeUnixNano(), - protoToAttributes(source.getAttributesList()), - source.getSum(), - source.hasMin(), - source.getMin(), - source.hasMax(), - source.getMax(), - source.getExplicitBoundsList(), - source.getBucketCountsList(), - exemplarListToDoubleExemplarDataList(source.getExemplarsList())); + source.start_time_unix_nano, + source.time_unix_nano, + protoToAttributes(source.attributes), + source.sum, + min > 0, + min, + max > 0, + max, + source.explicit_bounds, + source.bucket_counts, + exemplarListToDoubleExemplarDataList(source.exemplars)); } private static DoubleExemplarData exemplarToDoubleExemplarData(Exemplar source) { return ImmutableDoubleExemplarData.create( - protoToAttributes(source.getFilteredAttributesList()), - source.getTimeUnixNano(), + protoToAttributes(source.filtered_attributes), + source.time_unix_nano, createForExemplar(source), - source.getAsDouble()); + source.as_double); } private static LongExemplarData exemplarToLongExemplarData(Exemplar source) { return ImmutableLongExemplarData.create( - protoToAttributes(source.getFilteredAttributesList()), - source.getTimeUnixNano(), + protoToAttributes(source.filtered_attributes), + source.time_unix_nano, createForExemplar(source), - source.getAsInt()); + source.as_int); } private static SpanContext createForExemplar(Exemplar value) { return SpanContext.create( - ByteStringMapper.getInstance().protoToString(value.getTraceId()), - ByteStringMapper.getInstance().protoToString(value.getSpanId()), + ByteStringMapper.getInstance().protoToString(value.trace_id), + ByteStringMapper.getInstance().protoToString(value.span_id), TraceFlags.getSampled(), TraceState.getDefault()); } private static SummaryPointData summaryDataPointToSummaryPointData(SummaryDataPoint source) { return ImmutableSummaryPointData.create( - source.getStartTimeUnixNano(), - source.getTimeUnixNano(), - protoToAttributes(source.getAttributesList()), - source.getCount(), - source.getSum(), - valueAtQuantileListToValueAtQuantileList(source.getQuantileValuesList())); + source.start_time_unix_nano, + source.time_unix_nano, + protoToAttributes(source.attributes), + source.count, + source.sum, + valueAtQuantileListToValueAtQuantileList(source.quantile_values)); } private static ValueAtQuantile mapFromSummaryValueAtQuantileProto( SummaryDataPoint.ValueAtQuantile source) { - return ImmutableValueAtQuantile.create(source.getQuantile(), source.getValue()); + return ImmutableValueAtQuantile.create(source.quantile, source.value); } private static io.opentelemetry.sdk.metrics.data.AggregationTemporality @@ -620,53 +615,53 @@ private static ValueAtQuantile mapFromSummaryValueAtQuantileProto( private static GaugeData mapLongGaugeToSdk(Gauge gauge) { return ImmutableGaugeData.create( - numberDataPointListToLongPointDataCollection(gauge.getDataPointsList())); + numberDataPointListToLongPointDataCollection(gauge.data_points)); } private static GaugeData mapDoubleGaugeToSdk(Gauge gauge) { return ImmutableGaugeData.create( - numberDataPointListToDoublePointDataCollection(gauge.getDataPointsList())); + numberDataPointListToDoublePointDataCollection(gauge.data_points)); } private static SumData mapLongSumToSdk(Sum sum) { return ImmutableSumData.create( - sum.getIsMonotonic(), - mapAggregationTemporalityToSdk(sum.getAggregationTemporality()), - numberDataPointListToLongPointDataCollection(sum.getDataPointsList())); + sum.is_monotonic, + mapAggregationTemporalityToSdk(sum.aggregation_temporality), + numberDataPointListToLongPointDataCollection(sum.data_points)); } private static SumData mapDoubleSumToSdk(Sum sum) { return ImmutableSumData.create( - sum.getIsMonotonic(), - mapAggregationTemporalityToSdk(sum.getAggregationTemporality()), - numberDataPointListToDoublePointDataCollection(sum.getDataPointsList())); + sum.is_monotonic, + mapAggregationTemporalityToSdk(sum.aggregation_temporality), + numberDataPointListToDoublePointDataCollection(sum.data_points)); } private static DoublePointData mapDoubleNumberDataPointToSdk(NumberDataPoint source) { return ImmutableDoublePointData.create( - source.getStartTimeUnixNano(), - source.getTimeUnixNano(), - protoToAttributes(source.getAttributesList()), - source.getAsDouble(), - exemplarListToDoubleExemplarDataList(source.getExemplarsList())); + source.start_time_unix_nano, + source.time_unix_nano, + protoToAttributes(source.attributes), + source.as_double, + exemplarListToDoubleExemplarDataList(source.exemplars)); } private static LongPointData mapLongNumberDataPointToSdk(NumberDataPoint source) { return ImmutableLongPointData.create( - source.getStartTimeUnixNano(), - source.getTimeUnixNano(), - protoToAttributes(source.getAttributesList()), - source.getAsInt(), - exemplarListToLongExemplarDataList(source.getExemplarsList())); + source.start_time_unix_nano, + source.time_unix_nano, + protoToAttributes(source.attributes), + source.as_int, + exemplarListToLongExemplarDataList(source.exemplars)); } private static SummaryDataPoint.ValueAtQuantile valueAtQuantileToValueAtQuantile( ValueAtQuantile valueAtQuantile) { SummaryDataPoint.ValueAtQuantile.Builder builder = - SummaryDataPoint.ValueAtQuantile.newBuilder(); + new SummaryDataPoint.ValueAtQuantile.Builder(); - builder.setQuantile(valueAtQuantile.getQuantile()); - builder.setValue(valueAtQuantile.getValue()); + builder.quantile(valueAtQuantile.getQuantile()); + builder.value(valueAtQuantile.getValue()); return builder.build(); } @@ -755,8 +750,7 @@ private static List exemplarListToLongExemplarDataList(List attributesToProto(Attributes source) { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapper.java index 34b92f2d1..a81ab9957 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapper.java @@ -40,7 +40,7 @@ protected MetricData protoToSignalItem( @Override protected List getProtoResources(MetricsData protoData) { - return protoData.getResourceMetricsList(); + return protoData.resource_metrics; } @Override @@ -53,50 +53,50 @@ protected MetricsData createProtoData( for (Map.Entry> metricsByScope : instrumentationScopeInfoScopedMetricsMap.entrySet()) { ScopeMetrics.Builder scopeBuilder = createProtoScopeBuilder(metricsByScope.getKey()); - scopeBuilder.addAllMetrics(metricsByScope.getValue()); - resourceMetricsBuilder.addScopeMetrics(scopeBuilder.build()); + scopeBuilder.metrics.addAll(metricsByScope.getValue()); + resourceMetricsBuilder.scope_metrics.add(scopeBuilder.build()); } items.add(resourceMetricsBuilder.build()); }); - return MetricsData.newBuilder().addAllResourceMetrics(items).build(); + return new MetricsData.Builder().resource_metrics(items).build(); } private ScopeMetrics.Builder createProtoScopeBuilder(InstrumentationScopeInfo scopeInfo) { ScopeMetrics.Builder builder = - ScopeMetrics.newBuilder().setScope(instrumentationScopeToProto(scopeInfo)); + new ScopeMetrics.Builder().scope(instrumentationScopeToProto(scopeInfo)); if (scopeInfo.getSchemaUrl() != null) { - builder.setSchemaUrl(scopeInfo.getSchemaUrl()); + builder.schema_url(scopeInfo.getSchemaUrl()); } return builder; } private ResourceMetrics.Builder createProtoResourceBuilder(Resource resource) { ResourceMetrics.Builder builder = - ResourceMetrics.newBuilder().setResource(resourceToProto(resource)); + new ResourceMetrics.Builder().resource(resourceToProto(resource)); if (resource.getSchemaUrl() != null) { - builder.setSchemaUrl(resource.getSchemaUrl()); + builder.schema_url(resource.getSchemaUrl()); } return builder; } @Override protected List getSignalsFromProto(ScopeMetrics scopeSignals) { - return scopeSignals.getMetricsList(); + return scopeSignals.metrics; } @Override protected InstrumentationScopeInfo getInstrumentationScopeFromProto(ScopeMetrics scopeSignals) { - return protoToInstrumentationScopeInfo(scopeSignals.getScope(), scopeSignals.getSchemaUrl()); + return protoToInstrumentationScopeInfo(scopeSignals.scope, scopeSignals.schema_url); } @Override protected List getScopes(ResourceMetrics resourceSignal) { - return resourceSignal.getScopeMetricsList(); + return resourceSignal.scope_metrics; } @Override protected Resource getResourceFromProto(ResourceMetrics resourceSignal) { - return protoToResource(resourceSignal.getResource(), resourceSignal.getSchemaUrl()); + return protoToResource(resourceSignal.resource, resourceSignal.schema_url); } @Override diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapper.java index cfe5c2d59..18acf3a1f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapper.java @@ -33,7 +33,7 @@ protected Span signalItemToProto(SpanData sourceData) { @Override protected List getProtoResources(TracesData protoData) { - return protoData.getResourceSpansList(); + return protoData.resource_spans; } @Override @@ -52,32 +52,32 @@ protected TracesData createProtoData( for (Map.Entry> spansByScope : instrumentationScopeInfoScopedSpansMap.entrySet()) { ScopeSpans.Builder scopeBuilder = createProtoScopeBuilder(spansByScope.getKey()); - scopeBuilder.addAllSpans(spansByScope.getValue()); - resourceSpansBuilder.addScopeSpans(scopeBuilder.build()); + scopeBuilder.spans.addAll(spansByScope.getValue()); + resourceSpansBuilder.scope_spans.add(scopeBuilder.build()); } items.add(resourceSpansBuilder.build()); }); - return TracesData.newBuilder().addAllResourceSpans(items).build(); + return new TracesData.Builder().resource_spans(items).build(); } @Override protected List getSignalsFromProto(ScopeSpans scopeSignals) { - return scopeSignals.getSpansList(); + return scopeSignals.spans; } @Override protected InstrumentationScopeInfo getInstrumentationScopeFromProto(ScopeSpans scopeSignals) { - return protoToInstrumentationScopeInfo(scopeSignals.getScope(), scopeSignals.getSchemaUrl()); + return protoToInstrumentationScopeInfo(scopeSignals.scope, scopeSignals.schema_url); } @Override protected List getScopes(ResourceSpans resourceSignal) { - return resourceSignal.getScopeSpansList(); + return resourceSignal.scope_spans; } @Override protected Resource getResourceFromProto(ResourceSpans resourceSignal) { - return protoToResource(resourceSignal.getResource(), resourceSignal.getSchemaUrl()); + return protoToResource(resourceSignal.resource, resourceSignal.schema_url); } @Override @@ -91,10 +91,9 @@ protected InstrumentationScopeInfo getInstrumentationScopeInfo(SpanData source) } private ResourceSpans.Builder createProtoResourceBuilder(Resource resource) { - ResourceSpans.Builder builder = - ResourceSpans.newBuilder().setResource(resourceToProto(resource)); + ResourceSpans.Builder builder = new ResourceSpans.Builder().resource(resourceToProto(resource)); if (resource.getSchemaUrl() != null) { - builder.setSchemaUrl(resource.getSchemaUrl()); + builder.schema_url(resource.getSchemaUrl()); } return builder; } @@ -102,9 +101,9 @@ private ResourceSpans.Builder createProtoResourceBuilder(Resource resource) { private ScopeSpans.Builder createProtoScopeBuilder( InstrumentationScopeInfo instrumentationScopeInfo) { ScopeSpans.Builder builder = - ScopeSpans.newBuilder().setScope(instrumentationScopeToProto(instrumentationScopeInfo)); + new ScopeSpans.Builder().scope(instrumentationScopeToProto(instrumentationScopeInfo)); if (instrumentationScopeInfo.getSchemaUrl() != null) { - builder.setSchemaUrl(instrumentationScopeInfo.getSchemaUrl()); + builder.schema_url(instrumentationScopeInfo.getSchemaUrl()); } return builder; } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapper.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapper.java index 689be4d9b..34f63757a 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapper.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapper.java @@ -39,26 +39,26 @@ public static SpanDataMapper getInstance() { private final ByteStringMapper byteStringMapper = ByteStringMapper.getInstance(); public Span mapToProto(SpanData source) { - Span.Builder span = Span.newBuilder(); + Span.Builder span = new Span.Builder(); - span.setStartTimeUnixNano(source.getStartEpochNanos()); - span.setEndTimeUnixNano(source.getEndEpochNanos()); + span.start_time_unix_nano(source.getStartEpochNanos()); + span.end_time_unix_nano(source.getEndEpochNanos()); if (source.getEvents() != null) { for (EventData event : source.getEvents()) { - span.addEvents(eventDataToProto(event)); + span.events.add(eventDataToProto(event)); } } if (source.getLinks() != null) { for (LinkData link : source.getLinks()) { - span.addLinks(linkDataToProto(link)); + span.links.add(linkDataToProto(link)); } } - span.setTraceId(byteStringMapper.stringToProto(source.getTraceId())); - span.setSpanId(byteStringMapper.stringToProto(source.getSpanId())); - span.setParentSpanId(byteStringMapper.stringToProto(source.getParentSpanId())); - span.setName(source.getName()); - span.setKind(mapSpanKindToProto(source.getKind())); - span.setStatus(statusDataToProto(source.getStatus())); + span.trace_id(byteStringMapper.stringToProto(source.getTraceId())); + span.span_id(byteStringMapper.stringToProto(source.getSpanId())); + span.parent_span_id(byteStringMapper.stringToProto(source.getParentSpanId())); + span.name(source.getName()); + span.kind(mapSpanKindToProto(source.getKind())); + span.status(statusDataToProto(source.getStatus())); addSpanProtoExtras(source, span); @@ -66,26 +66,26 @@ public Span mapToProto(SpanData source) { } private static void addSpanProtoExtras(SpanData source, Span.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); - target.setDroppedAttributesCount( + target.attributes.addAll(attributesToProto(source.getAttributes())); + target.dropped_attributes_count( source.getTotalAttributeCount() - source.getAttributes().size()); - target.setDroppedEventsCount(source.getTotalRecordedEvents() - getListSize(source.getEvents())); - target.setDroppedLinksCount(source.getTotalRecordedLinks() - getListSize(source.getLinks())); - target.setTraceState(encodeTraceState(source.getSpanContext().getTraceState())); + target.dropped_events_count(source.getTotalRecordedEvents() - getListSize(source.getEvents())); + target.dropped_links_count(source.getTotalRecordedLinks() - getListSize(source.getLinks())); + target.trace_state(encodeTraceState(source.getSpanContext().getTraceState())); } public SpanData mapToSdk( Span source, Resource resource, InstrumentationScopeInfo instrumentationScopeInfo) { SpanDataImpl.Builder spanData = SpanDataImpl.builder(); - spanData.setStartEpochNanos(source.getStartTimeUnixNano()); - spanData.setEndEpochNanos(source.getEndTimeUnixNano()); - spanData.setEvents(eventListToEventDataList(source.getEventsList())); - spanData.setLinks(linkListToLinkDataList(source.getLinksList())); - spanData.setName(source.getName()); - spanData.setKind(mapSpanKindToSdk(source.getKind())); - if (source.hasStatus()) { - spanData.setStatus(mapStatusDataToSdk(source.getStatus())); + spanData.setStartEpochNanos(source.start_time_unix_nano); + spanData.setEndEpochNanos(source.end_time_unix_nano); + spanData.setEvents(eventListToEventDataList(source.events)); + spanData.setLinks(linkListToLinkDataList(source.links)); + spanData.setName(source.name); + spanData.setKind(mapSpanKindToSdk(source.kind)); + if (source.status != null) { + spanData.setStatus(mapStatusDataToSdk(source.status)); } addSpanDataExtras(source, spanData, resource, instrumentationScopeInfo); @@ -98,40 +98,40 @@ private static void addSpanDataExtras( SpanDataImpl.Builder target, Resource resource, InstrumentationScopeInfo instrumentationScopeInfo) { - Attributes attributes = protoToAttributes(source.getAttributesList()); + Attributes attributes = protoToAttributes(source.attributes); target.setAttributes(attributes); target.setResource(resource); target.setInstrumentationScopeInfo(instrumentationScopeInfo); - String traceId = ByteStringMapper.getInstance().protoToString(source.getTraceId()); + String traceId = ByteStringMapper.getInstance().protoToString(source.trace_id); target.setSpanContext( SpanContext.create( traceId, - ByteStringMapper.getInstance().protoToString(source.getSpanId()), + ByteStringMapper.getInstance().protoToString(source.span_id), TraceFlags.getSampled(), - decodeTraceState(source.getTraceState()))); + decodeTraceState(source.trace_state))); target.setParentSpanContext( SpanContext.create( traceId, - ByteStringMapper.getInstance().protoToString(source.getParentSpanId()), + ByteStringMapper.getInstance().protoToString(source.parent_span_id), TraceFlags.getSampled(), TraceState.getDefault())); - target.setTotalAttributeCount(source.getDroppedAttributesCount() + attributes.size()); + target.setTotalAttributeCount(source.dropped_attributes_count + attributes.size()); target.setTotalRecordedEvents( - calculateRecordedItems(source.getDroppedEventsCount(), source.getEventsCount())); + calculateRecordedItems(source.dropped_events_count, source.events.size())); target.setTotalRecordedLinks( - calculateRecordedItems(source.getDroppedLinksCount(), source.getLinksCount())); + calculateRecordedItems(source.dropped_links_count, source.links.size())); } private static StatusData mapStatusDataToSdk(Status source) { - return StatusData.create(getStatusCode(source.getCodeValue()), source.getMessage()); + return StatusData.create(getStatusCode(source.code.getValue()), source.message); } private static Span.Event eventDataToProto(EventData source) { - Span.Event.Builder event = Span.Event.newBuilder(); + Span.Event.Builder event = new Span.Event.Builder(); - event.setTimeUnixNano(source.getEpochNanos()); - event.setName(source.getName()); - event.setDroppedAttributesCount(source.getDroppedAttributesCount()); + event.time_unix_nano(source.getEpochNanos()); + event.name(source.getName()); + event.dropped_attributes_count(source.getDroppedAttributesCount()); addEventProtoExtras(source, event); @@ -139,14 +139,14 @@ private static Span.Event eventDataToProto(EventData source) { } private static void addEventProtoExtras(EventData source, Span.Event.Builder target) { - target.addAllAttributes(attributesToProto(source.getAttributes())); + target.attributes.addAll(attributesToProto(source.getAttributes())); } private static Status statusDataToProto(StatusData source) { - Status.Builder status = Status.newBuilder(); + Status.Builder status = new Status.Builder(); - status.setMessage(source.getDescription()); - status.setCode(mapStatusCodeToProto(source.getStatusCode())); + status.message(source.getDescription()); + status.code(mapStatusCodeToProto(source.getStatusCode())); return status.build(); } @@ -198,12 +198,12 @@ private static Status.StatusCode mapStatusCodeToProto(StatusCode source) { } private static EventData eventDataToSdk(Span.Event source) { - Attributes attributes = protoToAttributes(source.getAttributesList()); + Attributes attributes = protoToAttributes(source.attributes); return EventData.create( - source.getTimeUnixNano(), - source.getName(), + source.time_unix_nano, + source.name, attributes, - attributes.size() + source.getDroppedAttributesCount()); + attributes.size() + source.dropped_attributes_count); } private static SpanKind mapSpanKindToSdk(Span.SpanKind source) { @@ -251,14 +251,14 @@ private static List linkListToLinkDataList(List list) { } private static LinkData linkDataToSdk(Span.Link source) { - Attributes attributes = protoToAttributes(source.getAttributesList()); - int totalAttrCount = source.getDroppedAttributesCount() + attributes.size(); + Attributes attributes = protoToAttributes(source.attributes); + int totalAttrCount = source.dropped_attributes_count + attributes.size(); SpanContext spanContext = SpanContext.create( - ByteStringMapper.getInstance().protoToString(source.getTraceId()), - ByteStringMapper.getInstance().protoToString(source.getSpanId()), + ByteStringMapper.getInstance().protoToString(source.trace_id), + ByteStringMapper.getInstance().protoToString(source.span_id), TraceFlags.getSampled(), - decodeTraceState(source.getTraceState())); + decodeTraceState(source.trace_state)); return LinkData.create(spanContext, attributes, totalAttrCount); } @@ -304,14 +304,14 @@ private static TraceState decodeTraceState(@Nullable String source) { } private static Span.Link linkDataToProto(LinkData source) { - Span.Link.Builder builder = Span.Link.newBuilder(); + Span.Link.Builder builder = new Span.Link.Builder(); SpanContext spanContext = source.getSpanContext(); - builder.setTraceId(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); - builder.setSpanId(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); - builder.addAllAttributes(attributesToProto(source.getAttributes())); - builder.setDroppedAttributesCount( + builder.trace_id(ByteStringMapper.getInstance().stringToProto(spanContext.getTraceId())); + builder.span_id(ByteStringMapper.getInstance().stringToProto(spanContext.getSpanId())); + builder.attributes.addAll(attributesToProto(source.getAttributes())); + builder.dropped_attributes_count( source.getTotalAttributeCount() - source.getAttributes().size()); - builder.setTraceState(encodeTraceState(spanContext.getTraceState())); + builder.trace_state(encodeTraceState(spanContext.getTraceState())); return builder.build(); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/LogRecordDataSerializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/LogRecordDataSerializer.java index 6d0451ef7..2cd219a05 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/LogRecordDataSerializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/LogRecordDataSerializer.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers; -import com.google.protobuf.InvalidProtocolBufferException; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs.ProtoLogsDataMapper; +import io.opentelemetry.contrib.disk.buffering.internal.utils.ProtobufTools; import io.opentelemetry.proto.logs.v1.LogsData; import io.opentelemetry.sdk.logs.data.LogRecordData; import java.io.ByteArrayOutputStream; @@ -27,7 +27,9 @@ static LogRecordDataSerializer getInstance() { public byte[] serialize(Collection logRecordData) { LogsData proto = ProtoLogsDataMapper.getInstance().toProto(logRecordData); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - proto.writeDelimitedTo(out); + int size = LogsData.ADAPTER.encodedSize(proto); + ProtobufTools.writeRawVarint32(size, out); + proto.encode(out); return out.toByteArray(); } catch (IOException e) { throw new IllegalStateException(e); @@ -37,8 +39,8 @@ public byte[] serialize(Collection logRecordData) { @Override public List deserialize(byte[] source) { try { - return ProtoLogsDataMapper.getInstance().fromProto(LogsData.parseFrom(source)); - } catch (InvalidProtocolBufferException e) { + return ProtoLogsDataMapper.getInstance().fromProto(LogsData.ADAPTER.decode(source)); + } catch (IOException e) { throw new IllegalArgumentException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/MetricDataSerializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/MetricDataSerializer.java index 9e5722fbd..5c317980f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/MetricDataSerializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/MetricDataSerializer.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers; -import com.google.protobuf.InvalidProtocolBufferException; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.metrics.ProtoMetricsDataMapper; +import io.opentelemetry.contrib.disk.buffering.internal.utils.ProtobufTools; import io.opentelemetry.proto.metrics.v1.MetricsData; import io.opentelemetry.sdk.metrics.data.MetricData; import java.io.ByteArrayOutputStream; @@ -27,7 +27,9 @@ static MetricDataSerializer getInstance() { public byte[] serialize(Collection metricData) { MetricsData proto = ProtoMetricsDataMapper.getInstance().toProto(metricData); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - proto.writeDelimitedTo(out); + int size = MetricsData.ADAPTER.encodedSize(proto); + ProtobufTools.writeRawVarint32(size, out); + proto.encode(out); return out.toByteArray(); } catch (IOException e) { throw new IllegalStateException(e); @@ -37,8 +39,8 @@ public byte[] serialize(Collection metricData) { @Override public List deserialize(byte[] source) { try { - return ProtoMetricsDataMapper.getInstance().fromProto(MetricsData.parseFrom(source)); - } catch (InvalidProtocolBufferException e) { + return ProtoMetricsDataMapper.getInstance().fromProto(MetricsData.ADAPTER.decode(source)); + } catch (IOException e) { throw new IllegalArgumentException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/SpanDataSerializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/SpanDataSerializer.java index 1dc02034b..4c1cfdefd 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/SpanDataSerializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/serializers/SpanDataSerializer.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers; -import com.google.protobuf.InvalidProtocolBufferException; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.ProtoSpansDataMapper; +import io.opentelemetry.contrib.disk.buffering.internal.utils.ProtobufTools; import io.opentelemetry.proto.trace.v1.TracesData; import io.opentelemetry.sdk.trace.data.SpanData; import java.io.ByteArrayOutputStream; @@ -27,7 +27,9 @@ static SpanDataSerializer getInstance() { public byte[] serialize(Collection spanData) { TracesData proto = ProtoSpansDataMapper.getInstance().toProto(spanData); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - proto.writeDelimitedTo(out); + int size = TracesData.ADAPTER.encodedSize(proto); + ProtobufTools.writeRawVarint32(size, out); + proto.encode(out); return out.toByteArray(); } catch (IOException e) { throw new IllegalStateException(e); @@ -37,8 +39,8 @@ public byte[] serialize(Collection spanData) { @Override public List deserialize(byte[] source) { try { - return ProtoSpansDataMapper.getInstance().fromProto(TracesData.parseFrom(source)); - } catch (InvalidProtocolBufferException e) { + return ProtoSpansDataMapper.getInstance().fromProto(TracesData.ADAPTER.decode(source)); + } catch (IOException e) { throw new IllegalArgumentException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/reader/DelimitedProtoStreamReader.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/reader/DelimitedProtoStreamReader.java index ccdb0f1ed..0f9723c4c 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/reader/DelimitedProtoStreamReader.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/reader/DelimitedProtoStreamReader.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.storage.files.reader; -import com.google.protobuf.CodedInputStream; import io.opentelemetry.contrib.disk.buffering.internal.storage.files.utils.CountingInputStream; +import io.opentelemetry.contrib.disk.buffering.internal.utils.ProtobufTools; import java.io.IOException; import java.io.InputStream; import javax.annotation.Nullable; @@ -40,7 +40,7 @@ private int getNextItemSize() { if (firstByte == -1) { return 0; } - return CodedInputStream.readRawVarint32(firstByte, inputStream); + return ProtobufTools.readRawVarint32(firstByte, inputStream); } catch (IOException e) { return 0; } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/ProtobufTools.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/ProtobufTools.java new file mode 100644 index 000000000..04816e81e --- /dev/null +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/ProtobufTools.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.utils; + +import com.squareup.wire.ProtoAdapter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public final class ProtobufTools { + + private ProtobufTools() {} + + public static void writeRawVarint32(int value, OutputStream out) throws IOException { + ProtoAdapter.INT32.encode(out, value); + } + + /** This code has been taken from Google's protobuf CodedInputStream. */ + public static int readRawVarint32(int firstByte, InputStream input) throws IOException { + if ((firstByte & 0x80) == 0) { + return firstByte; + } + + int result = firstByte & 0x7f; + int offset = 7; + for (; offset < 32; offset += 7) { + int b = input.read(); + if (b == -1) { + throw new IllegalStateException(); + } + result |= (b & 0x7f) << offset; + if ((b & 0x80) == 0) { + return result; + } + } + // Keep reading up to 64 bits. + for (; offset < 64; offset += 7) { + int b = input.read(); + if (b == -1) { + throw new IllegalStateException(); + } + if ((b & 0x80) == 0) { + return result; + } + } + throw new IllegalStateException(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java index c4c4300e2..48a563300 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java @@ -87,10 +87,10 @@ void verifyConversionDataStructure() { LogsData result = mapToProto(signals); - List resourceLogsList = result.getResourceLogsList(); + List resourceLogsList = result.resource_logs; assertEquals(1, resourceLogsList.size()); - assertEquals(1, resourceLogsList.get(0).getScopeLogsList().size()); - assertEquals(1, resourceLogsList.get(0).getScopeLogsList().get(0).getLogRecordsList().size()); + assertEquals(1, resourceLogsList.get(0).scope_logs.size()); + assertEquals(1, resourceLogsList.get(0).scope_logs.get(0).log_records.size()); assertThat(mapFromProto(result)).containsExactlyInAnyOrderElementsOf(signals); } @@ -101,14 +101,14 @@ void verifyMultipleLogsWithSameResourceAndScope() { LogsData proto = mapToProto(signals); - List resourceLogsList = proto.getResourceLogsList(); + List resourceLogsList = proto.resource_logs; assertEquals(1, resourceLogsList.size()); - List scopeLogsList = resourceLogsList.get(0).getScopeLogsList(); + List scopeLogsList = resourceLogsList.get(0).scope_logs; assertEquals(1, scopeLogsList.size()); - List logRecords = scopeLogsList.get(0).getLogRecordsList(); + List logRecords = scopeLogsList.get(0).log_records; assertEquals(2, logRecords.size()); - assertEquals("Log body", logRecords.get(0).getBody().getStringValue()); - assertEquals("Other log body", logRecords.get(1).getBody().getStringValue()); + assertEquals("Log body", logRecords.get(0).body.string_value); + assertEquals("Other log body", logRecords.get(1).body.string_value); assertEquals(2, mapFromProto(proto).size()); @@ -122,14 +122,14 @@ void verifyMultipleLogsWithSameResourceDifferentScope() { LogsData proto = mapToProto(signals); - List resourceLogsList = proto.getResourceLogsList(); + List resourceLogsList = proto.resource_logs; assertEquals(1, resourceLogsList.size()); - List scopeLogsList = resourceLogsList.get(0).getScopeLogsList(); + List scopeLogsList = resourceLogsList.get(0).scope_logs; assertEquals(2, scopeLogsList.size()); ScopeLogs firstScope = scopeLogsList.get(0); ScopeLogs secondScope = scopeLogsList.get(1); - List firstScopeLogs = firstScope.getLogRecordsList(); - List secondScopeLogs = secondScope.getLogRecordsList(); + List firstScopeLogs = firstScope.log_records; + List secondScopeLogs = secondScope.log_records; assertEquals(1, firstScopeLogs.size()); assertEquals(1, secondScopeLogs.size()); @@ -142,18 +142,18 @@ void verifyMultipleLogsWithDifferentResource() { LogsData proto = mapToProto(signals); - List resourceLogsList = proto.getResourceLogsList(); + List resourceLogsList = proto.resource_logs; assertEquals(2, resourceLogsList.size()); ResourceLogs firstResourceLogs = resourceLogsList.get(0); ResourceLogs secondResourceLogs = resourceLogsList.get(1); - List firstScopeLogsList = firstResourceLogs.getScopeLogsList(); - List secondScopeLogsList = secondResourceLogs.getScopeLogsList(); + List firstScopeLogsList = firstResourceLogs.scope_logs; + List secondScopeLogsList = secondResourceLogs.scope_logs; assertEquals(1, firstScopeLogsList.size()); assertEquals(1, secondScopeLogsList.size()); ScopeLogs firstScope = firstScopeLogsList.get(0); ScopeLogs secondScope = secondScopeLogsList.get(0); - List firstScopeLogs = firstScope.getLogRecordsList(); - List secondScopeLogs = secondScope.getLogRecordsList(); + List firstScopeLogs = firstScope.log_records; + List secondScopeLogs = secondScope.log_records; assertEquals(1, firstScopeLogs.size()); assertEquals(1, secondScopeLogs.size()); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java index b2df173ec..16812f3b6 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java @@ -80,10 +80,10 @@ void verifyConversionDataStructure() { MetricsData proto = mapToProto(signals); - List resourceMetrics = proto.getResourceMetricsList(); + List resourceMetrics = proto.resource_metrics; assertEquals(1, resourceMetrics.size()); - assertEquals(1, resourceMetrics.get(0).getScopeMetricsList().size()); - assertEquals(1, resourceMetrics.get(0).getScopeMetricsList().get(0).getMetricsList().size()); + assertEquals(1, resourceMetrics.get(0).scope_metrics.size()); + assertEquals(1, resourceMetrics.get(0).scope_metrics.get(0).metrics.size()); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -94,11 +94,11 @@ void verifyMultipleMetricsWithSameResourceAndScope() { MetricsData proto = mapToProto(signals); - List resourceMetrics = proto.getResourceMetricsList(); + List resourceMetrics = proto.resource_metrics; assertEquals(1, resourceMetrics.size()); - List scopeMetrics = resourceMetrics.get(0).getScopeMetricsList(); + List scopeMetrics = resourceMetrics.get(0).scope_metrics; assertEquals(1, scopeMetrics.size()); - List metrics = scopeMetrics.get(0).getMetricsList(); + List metrics = scopeMetrics.get(0).metrics; assertEquals(2, metrics.size()); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); @@ -111,14 +111,14 @@ void verifyMultipleMetricsWithSameResourceDifferentScope() { MetricsData proto = mapToProto(signals); - List resourceMetrics = proto.getResourceMetricsList(); + List resourceMetrics = proto.resource_metrics; assertEquals(1, resourceMetrics.size()); - List scopeMetrics = resourceMetrics.get(0).getScopeMetricsList(); + List scopeMetrics = resourceMetrics.get(0).scope_metrics; assertEquals(2, scopeMetrics.size()); ScopeMetrics firstScope = scopeMetrics.get(0); ScopeMetrics secondScope = scopeMetrics.get(1); - List firstScopeMetrics = firstScope.getMetricsList(); - List secondScopeMetrics = secondScope.getMetricsList(); + List firstScopeMetrics = firstScope.metrics; + List secondScopeMetrics = secondScope.metrics; assertEquals(1, firstScopeMetrics.size()); assertEquals(1, secondScopeMetrics.size()); @@ -132,18 +132,18 @@ void verifyMultipleMetricsWithDifferentResource() { MetricsData proto = mapToProto(signals); - List resourceMetrics = proto.getResourceMetricsList(); + List resourceMetrics = proto.resource_metrics; assertEquals(2, resourceMetrics.size()); ResourceMetrics firstResourceMetrics = resourceMetrics.get(0); ResourceMetrics secondResourceMetrics = resourceMetrics.get(1); - List firstScopeMetrics = firstResourceMetrics.getScopeMetricsList(); - List secondScopeMetrics = secondResourceMetrics.getScopeMetricsList(); + List firstScopeMetrics = firstResourceMetrics.scope_metrics; + List secondScopeMetrics = secondResourceMetrics.scope_metrics; assertEquals(1, firstScopeMetrics.size()); assertEquals(1, secondScopeMetrics.size()); ScopeMetrics firstScope = firstScopeMetrics.get(0); ScopeMetrics secondScope = secondScopeMetrics.get(0); - List firstMetrics = firstScope.getMetricsList(); - List secondMetrics = secondScope.getMetricsList(); + List firstMetrics = firstScope.metrics; + List secondMetrics = secondScope.metrics; assertEquals(1, firstMetrics.size()); assertEquals(1, secondMetrics.size()); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java index 4aca59cf1..bdd9c053c 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java @@ -118,10 +118,10 @@ void verifyConversionDataStructure() { TracesData proto = mapToProto(signals); - List resourceSpans = proto.getResourceSpansList(); + List resourceSpans = proto.resource_spans; assertEquals(1, resourceSpans.size()); - assertEquals(1, resourceSpans.get(0).getScopeSpansList().size()); - assertEquals(1, resourceSpans.get(0).getScopeSpansList().get(0).getSpansList().size()); + assertEquals(1, resourceSpans.get(0).scope_spans.size()); + assertEquals(1, resourceSpans.get(0).scope_spans.get(0).spans.size()); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -132,11 +132,11 @@ void verifyMultipleSpansWithSameResourceAndScope() { TracesData proto = mapToProto(signals); - List resourceSpans = proto.getResourceSpansList(); + List resourceSpans = proto.resource_spans; assertEquals(1, resourceSpans.size()); - List scopeSpans = resourceSpans.get(0).getScopeSpansList(); + List scopeSpans = resourceSpans.get(0).scope_spans; assertEquals(1, scopeSpans.size()); - List spans = scopeSpans.get(0).getSpansList(); + List spans = scopeSpans.get(0).spans; assertEquals(2, spans.size()); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); @@ -148,14 +148,14 @@ void verifyMultipleSpansWithSameResourceDifferentScope() { TracesData proto = mapToProto(signals); - List resourceSpans = proto.getResourceSpansList(); + List resourceSpans = proto.resource_spans; assertEquals(1, resourceSpans.size()); - List scopeSpans = resourceSpans.get(0).getScopeSpansList(); + List scopeSpans = resourceSpans.get(0).scope_spans; assertEquals(2, scopeSpans.size()); ScopeSpans firstScope = scopeSpans.get(0); ScopeSpans secondScope = scopeSpans.get(1); - List firstScopeSpans = firstScope.getSpansList(); - List secondScopeSpans = secondScope.getSpansList(); + List firstScopeSpans = firstScope.spans; + List secondScopeSpans = secondScope.spans; assertEquals(1, firstScopeSpans.size()); assertEquals(1, secondScopeSpans.size()); @@ -168,18 +168,18 @@ void verifyMultipleSpansWithDifferentResource() { TracesData proto = mapToProto(signals); - List resourceSpans = proto.getResourceSpansList(); + List resourceSpans = proto.resource_spans; assertEquals(2, resourceSpans.size()); ResourceSpans firstResourceSpans = resourceSpans.get(0); ResourceSpans secondResourceSpans = resourceSpans.get(1); - List firstScopeSpans = firstResourceSpans.getScopeSpansList(); - List secondScopeSpans = secondResourceSpans.getScopeSpansList(); + List firstScopeSpans = firstResourceSpans.scope_spans; + List secondScopeSpans = secondResourceSpans.scope_spans; assertEquals(1, firstScopeSpans.size()); assertEquals(1, secondScopeSpans.size()); ScopeSpans firstScope = firstScopeSpans.get(0); ScopeSpans secondScope = secondScopeSpans.get(0); - List firstSpans = firstScope.getSpansList(); - List secondSpans = secondScope.getSpansList(); + List firstSpans = firstScope.spans; + List secondSpans = secondScope.spans; assertEquals(1, firstSpans.size()); assertEquals(1, secondSpans.size()); From 9ae650b2bcc336ef9b5a3d5b40d7b96054fc20cd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 14:33:46 +0200 Subject: [PATCH 041/108] Update dependency com.linecorp.armeria:armeria-bom to v1.25.2 (#1020) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 31d0642e5..b1ccf710c 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", "com.google.guava:guava-bom:32.1.2-jre", - "com.linecorp.armeria:armeria-bom:1.25.1", + "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.57.2", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", From 9d93cd902fc8d07a907487209736295b86d1173d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:36:16 -0700 Subject: [PATCH 042/108] Update dependency net.bytebuddy:byte-buddy-agent to v1.14.7 (#1021) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- runtime-attach/runtime-attach-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-attach/runtime-attach-core/build.gradle.kts b/runtime-attach/runtime-attach-core/build.gradle.kts index 41d65bae4..942a4006a 100644 --- a/runtime-attach/runtime-attach-core/build.gradle.kts +++ b/runtime-attach/runtime-attach-core/build.gradle.kts @@ -7,7 +7,7 @@ description = "To help in create an OpenTelemetry distro able to runtime attach otelJava.moduleName.set("io.opentelemetry.contrib.attach.core") dependencies { - implementation("net.bytebuddy:byte-buddy-agent:1.14.6") + implementation("net.bytebuddy:byte-buddy-agent:1.14.7") // Used by byte-buddy but not brought in as a transitive dependency. compileOnly("com.google.code.findbugs:annotations") From 2fc1a5024a9df5eaff5363b5d5d0b6576b290c18 Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 29 Aug 2023 05:35:51 +0800 Subject: [PATCH 043/108] Disable OTel SDK shutdown hook registration (#1022) --- .../java/io/opentelemetry/maven/OpenTelemetrySdkService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java index 63d3fa38e..c11985f94 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -94,6 +94,7 @@ public void initialize() { AutoConfiguredOpenTelemetrySdk.builder() .setServiceClassLoader(getClass().getClassLoader()) .addPropertiesSupplier(() -> properties) + .disableShutdownHook() .build(); if (logger.isDebugEnabled()) { From 9c58a399a633eab53d0d90b702c1a804e6ce5d89 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:56:33 -0700 Subject: [PATCH 044/108] Update plugin com.diffplug.spotless to v6.21.0 (#1024) Co-authored-by: renovate[bot] <29139614+renovate[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 41b625ec6..549db6fc9 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `kotlin-dsl` // When updating, update below in dependencies too - id("com.diffplug.spotless") version "6.20.0" + id("com.diffplug.spotless") version "6.21.0" } repositories { From 414a036e3dcade95e4d85715ab892401689ba4e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:56:43 -0700 Subject: [PATCH 045/108] Update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.21.0 (#1023) Co-authored-by: renovate[bot] <29139614+renovate[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 549db6fc9..b5962b66a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,7 @@ repositories { dependencies { // When updating, update above in plugins too - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.20.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.21.0") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.14.1") From 72c6603c62777315d98152e6b2a91d8228acc31a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 18:16:36 -0700 Subject: [PATCH 046/108] Update dependency com.uber.nullaway:nullaway to v0.10.13 (#1025) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index b1ccf710c..0a6cef4d4 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -50,7 +50,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", - "com.uber.nullaway:nullaway:0.10.12", + "com.uber.nullaway:nullaway:0.10.13", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From 37e85b9aa8d32af8db7621e5863a4e58cb98a55b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:17:52 +0200 Subject: [PATCH 047/108] Update slf4jVersion to v2.0.9 (#1026) --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 0a6cef4d4..7e0ca816a 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -22,7 +22,7 @@ val autoValueVersion = "1.10.3" val errorProneVersion = "2.21.1" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" -val slf4jVersion = "2.0.7" +val slf4jVersion = "2.0.9" val CORE_DEPENDENCIES = listOf( "com.google.auto.service:auto-service:${autoServiceVersion}", From c193c0b1a1271277dbec5ad2630d041726eca42c Mon Sep 17 00:00:00 2001 From: jason plumb <75337021+breedx-splk@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:15:08 -0700 Subject: [PATCH 048/108] Add some libraries missing from the main README (#1028) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 391f7bc04..d38018487 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,16 @@ feature or via instrumentation, this project is hopefully for you. * [AWS Resources](./aws-resources/README.md) * [AWS X-Ray SDK Support](./aws-xray/README.md) * [AWS X-Ray Propagator](./aws-xray-propagator/README.md) -* [Consistent sampling](./consistent-sampling/README.md) +* [Consistent Sampling](./consistent-sampling/README.md) +* [Disk Buffering](./disk-buffering/README.md) * [JMX Metric Gatherer](./jmx-metrics/README.md) +* [No-Op API](./noop-api/README.md) * [OpenTelemetry Maven Extension](./maven-extension/README.md) +* [Prometheus Client Bridge](./prometheus-client-bridge/README.md) +* [Resource Providers](./resource-providers/README.md) * [Runtime Attach](./runtime-attach/README.md) * [Samplers](./samplers/README.md) +* [Static Instrumenter](./static-instrumenter/README.md) ## Getting Started From 2480afd12e017f1b53c98af618765ed94c20eb59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:22:25 -0700 Subject: [PATCH 049/108] Update actions/checkout action to v4 (#1027) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/backport.yml | 2 +- .github/workflows/build.yml | 8 ++++---- .github/workflows/codeql-daily.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- .../workflows/issue-management-feedback-label.yml | 2 +- .github/workflows/prepare-patch-release.yml | 2 +- .github/workflows/prepare-release-branch.yml | 6 +++--- .github/workflows/release.yml | 14 +++++++------- .github/workflows/reusable-markdown-link-check.yml | 2 +- .github/workflows/reusable-markdown-lint.yml | 2 +- .github/workflows/reusable-misspell-check.yml | 2 +- .github/workflows/reusable-shell-script-check.yml | 2 +- .../workflows/reusable-workflow-notification.yml | 2 +- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 561ff8c55..760c3e999 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -16,7 +16,7 @@ jobs: exit 1 fi - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # history is needed to run git cherry-pick below fetch-depth: 0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fdb458f1e..1abb23f2a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK for running Gradle uses: actions/setup-java@v3 @@ -44,7 +44,7 @@ jobs: - 20 fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: setup-test-java name: Set up JDK ${{ matrix.test-java-version }} for running tests @@ -75,7 +75,7 @@ jobs: integration-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK for running Gradle uses: actions/setup-java@v3 @@ -127,7 +127,7 @@ jobs: - integration-test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK for running Gradle uses: actions/setup-java@v3 diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 649883690..08d986743 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Java 17 uses: actions/setup-java@v3 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 75f8f8d35..b42e7b96b 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -11,6 +11,6 @@ jobs: validation: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: gradle/wrapper-validation-action@v1.1.0 diff --git a/.github/workflows/issue-management-feedback-label.yml b/.github/workflows/issue-management-feedback-label.yml index fe3c9aa2e..da9aa75b7 100644 --- a/.github/workflows/issue-management-feedback-label.yml +++ b/.github/workflows/issue-management-feedback-label.yml @@ -11,7 +11,7 @@ jobs: github.event.comment.user.login == github.event.issue.user.login runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Remove label env: diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml index 6210753d8..d9a9ed38f 100644 --- a/.github/workflows/prepare-patch-release.yml +++ b/.github/workflows/prepare-patch-release.yml @@ -6,7 +6,7 @@ jobs: prepare-patch-release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | if [[ ! $GITHUB_REF_NAME =~ ^release/v[0-9]+\.[0-9]+\.x$ ]]; then diff --git a/.github/workflows/prepare-release-branch.yml b/.github/workflows/prepare-release-branch.yml index e26dec913..43859db70 100644 --- a/.github/workflows/prepare-release-branch.yml +++ b/.github/workflows/prepare-release-branch.yml @@ -6,7 +6,7 @@ jobs: prereqs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Verify prerequisites run: | @@ -25,7 +25,7 @@ jobs: needs: - prereqs steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create release branch run: | @@ -74,7 +74,7 @@ jobs: needs: - prereqs steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set environment variables run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6046be5ca..815174172 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK for running Gradle uses: actions/setup-java@v3 @@ -29,7 +29,7 @@ jobs: integration-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK for running Gradle uses: actions/setup-java@v3 @@ -63,7 +63,7 @@ jobs: exit 1 fi - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set environment variables run: | @@ -92,7 +92,7 @@ jobs: # check out main branch to verify there won't be problems with merging the change log # at the end of this workflow - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: main @@ -107,7 +107,7 @@ jobs: fi # back to the release branch - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # tags are needed for the generate-release-contributors.sh script fetch-depth: 0 @@ -187,7 +187,7 @@ jobs: needs: - release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Copy change log section from release branch env: @@ -196,7 +196,7 @@ jobs: sed -n "0,/^## Version $VERSION /d;/^## Version /q;p" CHANGELOG.md \ > /tmp/changelog-section.md - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: main diff --git a/.github/workflows/reusable-markdown-link-check.yml b/.github/workflows/reusable-markdown-link-check.yml index ba995d6de..4e7ad15c4 100644 --- a/.github/workflows/reusable-markdown-link-check.yml +++ b/.github/workflows/reusable-markdown-link-check.yml @@ -7,7 +7,7 @@ jobs: markdown-link-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install markdown-link-check # TODO(jack-berg): use latest when config file reading bug is fixed: https://github.com/tcort/markdown-link-check/issues/246 diff --git a/.github/workflows/reusable-markdown-lint.yml b/.github/workflows/reusable-markdown-lint.yml index 0b961cb46..31ce12900 100644 --- a/.github/workflows/reusable-markdown-lint.yml +++ b/.github/workflows/reusable-markdown-lint.yml @@ -7,7 +7,7 @@ jobs: markdown-lint-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install markdownlint run: npm install -g markdownlint-cli diff --git a/.github/workflows/reusable-misspell-check.yml b/.github/workflows/reusable-misspell-check.yml index 36fbb8620..8bb5e8185 100644 --- a/.github/workflows/reusable-misspell-check.yml +++ b/.github/workflows/reusable-misspell-check.yml @@ -7,7 +7,7 @@ jobs: misspell-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install misspell run: | diff --git a/.github/workflows/reusable-shell-script-check.yml b/.github/workflows/reusable-shell-script-check.yml index 6e76af861..8ad84d752 100644 --- a/.github/workflows/reusable-shell-script-check.yml +++ b/.github/workflows/reusable-shell-script-check.yml @@ -7,7 +7,7 @@ jobs: shell-script-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install shell check run: wget -qO- "https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz" | tar -xJv diff --git a/.github/workflows/reusable-workflow-notification.yml b/.github/workflows/reusable-workflow-notification.yml index 898dc214e..b621ffb95 100644 --- a/.github/workflows/reusable-workflow-notification.yml +++ b/.github/workflows/reusable-workflow-notification.yml @@ -13,7 +13,7 @@ jobs: workflow-notification: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Open issue or add comment if issue already open env: From 7e4637a56a494c23131efd0da8cd78e2e652ecc9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:25:10 +0200 Subject: [PATCH 050/108] Update dependency io.grpc:grpc-bom to v1.58.0 (#1029) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 7e0ca816a..c86c5bdc5 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -12,7 +12,7 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:32.1.2-jre", "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", - "io.grpc:grpc-bom:1.57.2", + "io.grpc:grpc-bom:1.58.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", "org.testcontainers:testcontainers-bom:1.19.0" ) From d56ea370f18c87b195f5a7818d860e4ac14b1262 Mon Sep 17 00:00:00 2001 From: LikeTheSalad <56847527+LikeTheSalad@users.noreply.github.com> Date: Fri, 8 Sep 2023 00:56:55 +0200 Subject: [PATCH 051/108] Signals processing (#1014) --- .github/component_owners.yml | 3 + processors/README.md | 10 ++ processors/build.gradle.kts | 17 ++ .../InterceptableLogRecordExporter.java | 39 +++++ .../InterceptableMetricExporter.java | 45 ++++++ .../InterceptableSpanExporter.java | 38 +++++ .../contrib/interceptor/api/Interceptor.java | 43 +++++ .../common/ComposableInterceptor.java | 32 ++++ .../InterceptableLogRecordExporterTest.java | 153 ++++++++++++++++++ .../InterceptableMetricExporterTest.java | 132 +++++++++++++++ .../InterceptableSpanExporterTest.java | 94 +++++++++++ settings.gradle.kts | 1 + 12 files changed, 607 insertions(+) create mode 100644 processors/README.md create mode 100644 processors/build.gradle.kts create mode 100644 processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporter.java create mode 100644 processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporter.java create mode 100644 processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporter.java create mode 100644 processors/src/main/java/io/opentelemetry/contrib/interceptor/api/Interceptor.java create mode 100644 processors/src/main/java/io/opentelemetry/contrib/interceptor/common/ComposableInterceptor.java create mode 100644 processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java create mode 100644 processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java create mode 100644 processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java diff --git a/.github/component_owners.yml b/.github/component_owners.yml index 9c7e26c0e..b42a6ef5f 100644 --- a/.github/component_owners.yml +++ b/.github/component_owners.yml @@ -47,6 +47,9 @@ components: - HaloFour noop-api: - jack-berg + processors: + - LikeTheSalad + - breedx-splk prometheus-collector: - jkwatson resource-providers: diff --git a/processors/README.md b/processors/README.md new file mode 100644 index 000000000..eda5acee6 --- /dev/null +++ b/processors/README.md @@ -0,0 +1,10 @@ +# Processors + +This module provides tools to intercept and process signals globally. + +## Component owners + +- [Cesar Munoz](https://github.com/LikeTheSalad), Elastic +- [Jason Plumb](https://github.com/breedx-splk), Splunk + +Learn more about component owners in [component_owners.yml](../.github/component_owners.yml). diff --git a/processors/build.gradle.kts b/processors/build.gradle.kts new file mode 100644 index 000000000..c24118550 --- /dev/null +++ b/processors/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("otel.java-conventions") + id("otel.publish-conventions") +} + +description = "Tools to intercept and process signals globally." +otelJava.moduleName.set("io.opentelemetry.contrib.processors") + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +dependencies { + api("io.opentelemetry:opentelemetry-sdk") + testImplementation("io.opentelemetry:opentelemetry-sdk-testing") +} diff --git a/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporter.java b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporter.java new file mode 100644 index 000000000..732316854 --- /dev/null +++ b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporter.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import io.opentelemetry.contrib.interceptor.api.Interceptor; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.util.Collection; + +/** Intercepts logs before delegating them to the real exporter. */ +public final class InterceptableLogRecordExporter implements LogRecordExporter { + private final LogRecordExporter delegate; + private final Interceptor interceptor; + + public InterceptableLogRecordExporter( + LogRecordExporter delegate, Interceptor interceptor) { + this.delegate = delegate; + this.interceptor = interceptor; + } + + @Override + public CompletableResultCode export(Collection logs) { + return delegate.export(interceptor.interceptAll(logs)); + } + + @Override + public CompletableResultCode flush() { + return delegate.flush(); + } + + @Override + public CompletableResultCode shutdown() { + return delegate.shutdown(); + } +} diff --git a/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporter.java b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporter.java new file mode 100644 index 000000000..4422fde75 --- /dev/null +++ b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporter.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import io.opentelemetry.contrib.interceptor.api.Interceptor; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.metrics.InstrumentType; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import java.util.Collection; + +/** Intercepts metrics before delegating them to the real exporter. */ +public final class InterceptableMetricExporter implements MetricExporter { + private final MetricExporter delegate; + private final Interceptor interceptor; + + public InterceptableMetricExporter(MetricExporter delegate, Interceptor interceptor) { + this.delegate = delegate; + this.interceptor = interceptor; + } + + @Override + public CompletableResultCode export(Collection metrics) { + return delegate.export(interceptor.interceptAll(metrics)); + } + + @Override + public CompletableResultCode flush() { + return delegate.flush(); + } + + @Override + public CompletableResultCode shutdown() { + return delegate.shutdown(); + } + + @Override + public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) { + return delegate.getAggregationTemporality(instrumentType); + } +} diff --git a/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporter.java b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporter.java new file mode 100644 index 000000000..275393a99 --- /dev/null +++ b/processors/src/main/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporter.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import io.opentelemetry.contrib.interceptor.api.Interceptor; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.util.Collection; + +/** Intercepts spans before delegating them to the real exporter. */ +public final class InterceptableSpanExporter implements SpanExporter { + private final SpanExporter delegate; + private final Interceptor interceptor; + + public InterceptableSpanExporter(SpanExporter delegate, Interceptor interceptor) { + this.delegate = delegate; + this.interceptor = interceptor; + } + + @Override + public CompletableResultCode export(Collection spans) { + return delegate.export(interceptor.interceptAll(spans)); + } + + @Override + public CompletableResultCode flush() { + return delegate.flush(); + } + + @Override + public CompletableResultCode shutdown() { + return delegate.shutdown(); + } +} diff --git a/processors/src/main/java/io/opentelemetry/contrib/interceptor/api/Interceptor.java b/processors/src/main/java/io/opentelemetry/contrib/interceptor/api/Interceptor.java new file mode 100644 index 000000000..f15246c10 --- /dev/null +++ b/processors/src/main/java/io/opentelemetry/contrib/interceptor/api/Interceptor.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor.api; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nullable; + +/** + * Intercepts a signal before it gets exported. The signal can get updated and/or filtered out based + * on each interceptor implementation. + */ +public interface Interceptor { + + /** + * Intercepts a signal. + * + * @param item The signal object. + * @return The received signal modified (or null for excluding this signal from getting exported). + * If there's no operation needed to be done for a specific signal, it should be returned as + * is. + */ + @Nullable + T intercept(T item); + + /** Intercepts a collection of signals. */ + default Collection interceptAll(Collection items) { + List result = new ArrayList<>(); + + for (T item : items) { + T intercepted = intercept(item); + if (intercepted != null) { + result.add(intercepted); + } + } + + return result; + } +} diff --git a/processors/src/main/java/io/opentelemetry/contrib/interceptor/common/ComposableInterceptor.java b/processors/src/main/java/io/opentelemetry/contrib/interceptor/common/ComposableInterceptor.java new file mode 100644 index 000000000..01fd4c8f5 --- /dev/null +++ b/processors/src/main/java/io/opentelemetry/contrib/interceptor/common/ComposableInterceptor.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor.common; + +import io.opentelemetry.contrib.interceptor.api.Interceptor; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.annotation.Nullable; + +/** Allows to run an item through a list of interceptors in the order they were added. */ +public final class ComposableInterceptor implements Interceptor { + private final CopyOnWriteArrayList> interceptors = new CopyOnWriteArrayList<>(); + + public void add(Interceptor interceptor) { + interceptors.addIfAbsent(interceptor); + } + + @Nullable + @Override + public T intercept(T item) { + T intercepted = item; + for (Interceptor interceptor : interceptors) { + intercepted = interceptor.intercept(intercepted); + if (intercepted == null) { + break; + } + } + return intercepted; + } +} diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java new file mode 100644 index 000000000..ff336b347 --- /dev/null +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java @@ -0,0 +1,153 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.contrib.interceptor.common.ComposableInterceptor; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.data.Body; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InterceptableLogRecordExporterTest { + private InMemoryLogRecordExporter memoryLogRecordExporter; + private Logger logger; + private ComposableInterceptor interceptor; + + @BeforeEach + void setUp() { + memoryLogRecordExporter = InMemoryLogRecordExporter.create(); + interceptor = new ComposableInterceptor<>(); + logger = + SdkLoggerProvider.builder() + .addLogRecordProcessor( + SimpleLogRecordProcessor.create( + new InterceptableLogRecordExporter(memoryLogRecordExporter, interceptor))) + .build() + .get("TestScope"); + } + + @Test + void verifyLogModification() { + interceptor.add( + item -> { + ModifiableLogRecordData modified = new ModifiableLogRecordData(item); + modified.attributes.put("global.attr", "from interceptor"); + return modified; + }); + + logger + .logRecordBuilder() + .setBody("One log") + .setAttribute(AttributeKey.stringKey("local.attr"), "local") + .emit(); + + List finishedLogRecordItems = + memoryLogRecordExporter.getFinishedLogRecordItems(); + assertEquals(1, finishedLogRecordItems.size()); + LogRecordData logRecordData = finishedLogRecordItems.get(0); + assertEquals(2, logRecordData.getAttributes().size()); + assertEquals( + "from interceptor", + logRecordData.getAttributes().get(AttributeKey.stringKey("global.attr"))); + assertEquals("local", logRecordData.getAttributes().get(AttributeKey.stringKey("local.attr"))); + } + + @Test + void verifyLogFiltering() { + interceptor.add( + item -> { + if (item.getBody().asString().contains("deleted")) { + return null; + } + return item; + }); + + logger.logRecordBuilder().setBody("One log").emit(); + logger.logRecordBuilder().setBody("This log will be deleted").emit(); + logger.logRecordBuilder().setBody("Another log").emit(); + + List finishedLogRecordItems = + memoryLogRecordExporter.getFinishedLogRecordItems(); + assertEquals(2, finishedLogRecordItems.size()); + assertEquals("One log", finishedLogRecordItems.get(0).getBody().asString()); + assertEquals("Another log", finishedLogRecordItems.get(1).getBody().asString()); + } + + private static class ModifiableLogRecordData implements LogRecordData { + private final LogRecordData delegate; + private final AttributesBuilder attributes = Attributes.builder(); + + private ModifiableLogRecordData(LogRecordData delegate) { + this.delegate = delegate; + } + + @Override + public Resource getResource() { + return delegate.getResource(); + } + + @Override + public InstrumentationScopeInfo getInstrumentationScopeInfo() { + return delegate.getInstrumentationScopeInfo(); + } + + @Override + public long getTimestampEpochNanos() { + return delegate.getTimestampEpochNanos(); + } + + @Override + public long getObservedTimestampEpochNanos() { + return delegate.getObservedTimestampEpochNanos(); + } + + @Override + public SpanContext getSpanContext() { + return delegate.getSpanContext(); + } + + @Override + public Severity getSeverity() { + return delegate.getSeverity(); + } + + @Nullable + @Override + public String getSeverityText() { + return delegate.getSeverityText(); + } + + @Override + public Body getBody() { + return delegate.getBody(); + } + + @Override + public Attributes getAttributes() { + return attributes.putAll(delegate.getAttributes()).build(); + } + + @Override + public int getTotalAttributeCount() { + return delegate.getTotalAttributeCount(); + } + } +} diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java new file mode 100644 index 000000000..6b12d5f1a --- /dev/null +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java @@ -0,0 +1,132 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.contrib.interceptor.common.ComposableInterceptor; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.data.Data; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.data.MetricDataType; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InterceptableMetricExporterTest { + private InMemoryMetricExporter memoryMetricExporter; + private SdkMeterProvider meterProvider; + private Meter meter; + private ComposableInterceptor interceptor; + + @BeforeEach + void setUp() { + memoryMetricExporter = InMemoryMetricExporter.create(); + interceptor = new ComposableInterceptor<>(); + meterProvider = + SdkMeterProvider.builder() + .registerMetricReader( + PeriodicMetricReader.create( + new InterceptableMetricExporter(memoryMetricExporter, interceptor))) + .build(); + meter = meterProvider.get("TestScope"); + } + + @Test + void verifyMetricModification() { + interceptor.add( + item -> { + ModifiableMetricData modified = new ModifiableMetricData(item); + modified.name = "ModifiedName"; + return modified; + }); + + meter.counterBuilder("OneCounter").build().add(1); + meterProvider.forceFlush(); + + List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); + assertEquals(1, finishedMetricItems.size()); + assertEquals("ModifiedName", finishedMetricItems.get(0).getName()); + } + + @Test + void verifyMetricFiltering() { + interceptor.add( + item -> { + if (item.getName().contains("Deleted")) { + return null; + } + return item; + }); + + meter.counterBuilder("OneCounter").build().add(1); + meter.counterBuilder("DeletedCounter").build().add(1); + meter.counterBuilder("AnotherCounter").build().add(1); + meterProvider.forceFlush(); + + List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); + assertEquals(2, finishedMetricItems.size()); + List names = new ArrayList<>(); + for (MetricData item : finishedMetricItems) { + names.add(item.getName()); + } + assertThat(names).containsExactlyInAnyOrder("OneCounter", "AnotherCounter"); + } + + private static class ModifiableMetricData implements MetricData { + private final MetricData delegate; + private String name; + + private ModifiableMetricData(MetricData delegate) { + this.delegate = delegate; + } + + @Override + public Resource getResource() { + return delegate.getResource(); + } + + @Override + public InstrumentationScopeInfo getInstrumentationScopeInfo() { + return delegate.getInstrumentationScopeInfo(); + } + + @Override + public String getName() { + if (name != null) { + return name; + } + return delegate.getName(); + } + + @Override + public String getDescription() { + return delegate.getDescription(); + } + + @Override + public String getUnit() { + return delegate.getUnit(); + } + + @Override + public MetricDataType getType() { + return delegate.getType(); + } + + @Override + public Data getData() { + return delegate.getData(); + } + } +} diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java new file mode 100644 index 000000000..35c3afaaa --- /dev/null +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java @@ -0,0 +1,94 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.interceptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.contrib.interceptor.common.ComposableInterceptor; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.DelegatingSpanData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InterceptableSpanExporterTest { + private InMemorySpanExporter memorySpanExporter; + private Tracer tracer; + private ComposableInterceptor interceptor; + + @BeforeEach + void setUp() { + memorySpanExporter = InMemorySpanExporter.create(); + interceptor = new ComposableInterceptor<>(); + tracer = + SdkTracerProvider.builder() + .addSpanProcessor( + SimpleSpanProcessor.create( + new InterceptableSpanExporter(memorySpanExporter, interceptor))) + .build() + .get("TestScope"); + } + + @Test + void verifySpanModification() { + interceptor.add( + item -> { + ModifiableSpanData modified = new ModifiableSpanData(item); + modified.attributes.put("global.attr", "from interceptor"); + return modified; + }); + + tracer.spanBuilder("Test span").setAttribute("local.attr", 10).startSpan().end(); + + List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); + assertEquals(1, finishedSpanItems.size()); + SpanData spanData = finishedSpanItems.get(0); + assertEquals(2, spanData.getAttributes().size()); + assertEquals( + "from interceptor", spanData.getAttributes().get(AttributeKey.stringKey("global.attr"))); + assertEquals(10, spanData.getAttributes().get(AttributeKey.longKey("local.attr"))); + } + + @Test + void verifySpanFiltering() { + interceptor.add( + item -> { + if (item.getName().contains("deleted")) { + return null; + } + return item; + }); + + tracer.spanBuilder("One span").startSpan().end(); + tracer.spanBuilder("This will get deleted").startSpan().end(); + tracer.spanBuilder("Another span").startSpan().end(); + + List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); + assertEquals(2, finishedSpanItems.size()); + assertEquals("One span", finishedSpanItems.get(0).getName()); + assertEquals("Another span", finishedSpanItems.get(1).getName()); + } + + private static class ModifiableSpanData extends DelegatingSpanData { + private final AttributesBuilder attributes = Attributes.builder(); + + protected ModifiableSpanData(SpanData delegate) { + super(delegate); + } + + @Override + public Attributes getAttributes() { + return attributes.putAll(super.getAttributes()).build(); + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 8e312c449..5a86947e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -76,6 +76,7 @@ include(":jmx-metrics") include(":maven-extension") include(":micrometer-meter-provider") include(":noop-api") +include(":processors") include(":prometheus-client-bridge") include(":resource-providers") include(":runtime-attach:runtime-attach") From 43cabe43bead202d077e28d16774f9547d2b0891 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 08:31:05 +0200 Subject: [PATCH 052/108] Update dependency com.uber.nullaway:nullaway to v0.10.14 (#1031) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index c86c5bdc5..9b2300149 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -50,7 +50,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", - "com.uber.nullaway:nullaway:0.10.13", + "com.uber.nullaway:nullaway:0.10.14", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From b13576dca45cc1a630a762fea2df0d88da201b48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 10:06:01 +0200 Subject: [PATCH 053/108] Update autoValueVersion to v1.10.4 (#1033) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 9b2300149..7e268da30 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -18,7 +18,7 @@ val DEPENDENCY_BOMS = listOf( ) val autoServiceVersion = "1.1.1" -val autoValueVersion = "1.10.3" +val autoValueVersion = "1.10.4" val errorProneVersion = "2.21.1" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" From b05023dc63e770326d087373f6de8c5a87550fb9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 12:30:57 -0700 Subject: [PATCH 054/108] Update gradle enterprise packages to v3.15 (#1038) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- settings.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b5962b66a..306e62c30 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.21.0") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") - implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.14.1") + implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.15") } spotless { diff --git a/settings.gradle.kts b/settings.gradle.kts index 5a86947e2..46f8f3d46 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ pluginManagement { plugins { id("com.github.johnrengelman.shadow") version "8.1.1" - id("com.gradle.enterprise") version "3.14.1" + id("com.gradle.enterprise") version "3.15" id("io.github.gradle-nexus.publish-plugin") version "1.3.0" } } From 424fbddd1dc7563ab33a50fb2aa2b32e0b838ec4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 12:56:25 -0700 Subject: [PATCH 055/108] Update micrometer packages to v1.11.4 (#1037) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index 64db724a8..e73ce74c4 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -19,14 +19,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.11.3") + testImplementation("io.micrometer:micrometer-core:1.11.4") } testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.11.3") + implementation("io.micrometer:micrometer-registry-prometheus:1.11.4") } } } From bb019ac15e997c2f2c98ef20fd86c60e5c3aac55 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 12:56:48 -0700 Subject: [PATCH 056/108] Update dependency net.bytebuddy:byte-buddy-agent to v1.14.8 (#1040) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- runtime-attach/runtime-attach-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-attach/runtime-attach-core/build.gradle.kts b/runtime-attach/runtime-attach-core/build.gradle.kts index 942a4006a..71314c7b4 100644 --- a/runtime-attach/runtime-attach-core/build.gradle.kts +++ b/runtime-attach/runtime-attach-core/build.gradle.kts @@ -7,7 +7,7 @@ description = "To help in create an OpenTelemetry distro able to runtime attach otelJava.moduleName.set("io.opentelemetry.contrib.attach.core") dependencies { - implementation("net.bytebuddy:byte-buddy-agent:1.14.7") + implementation("net.bytebuddy:byte-buddy-agent:1.14.8") // Used by byte-buddy but not brought in as a transitive dependency. compileOnly("com.google.code.findbugs:annotations") From d983e7f515b43c3725e7b07719aa5f9b207d1ac3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 08:48:26 +0200 Subject: [PATCH 057/108] Update dependency io.opentelemetry.javaagent:opentelemetry-javaagent to v1.30.0 (#1039) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 7e268da30..d70545a80 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -46,7 +46,7 @@ val CORE_DEPENDENCIES = listOf( ) val DEPENDENCIES = listOf( - "io.opentelemetry.javaagent:opentelemetry-javaagent:1.29.0", + "io.opentelemetry.javaagent:opentelemetry-javaagent:1.30.0", "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", From 811d8d7e1cdcefb03ed2a20ae09312aa16a3f33a Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 17 Sep 2023 11:11:49 -0700 Subject: [PATCH 058/108] Update otel version (#1041) --- .github/renovate.json5 | 10 +++++ aws-resources/build.gradle.kts | 2 +- .../aws/resource/BeanstalkResource.java | 2 +- .../contrib/aws/resource/Ec2Resource.java | 2 +- .../contrib/aws/resource/EcsResource.java | 2 +- .../contrib/aws/resource/EksResource.java | 2 +- .../contrib/aws/resource/LambdaResource.java | 2 +- .../aws/resource/BeanstalkResourceTest.java | 2 +- .../contrib/aws/resource/Ec2ResourceTest.java | 2 +- .../contrib/aws/resource/EcsResourceTest.java | 2 +- .../contrib/aws/resource/EksResourceTest.java | 2 +- .../aws/resource/LambdaResourceTest.java | 2 +- aws-xray/build.gradle.kts | 7 ++++ dependencyManagement/build.gradle.kts | 3 +- jmx-metrics/build.gradle.kts | 4 -- maven-extension/build.gradle.kts | 7 ++++ resource-providers/build.gradle.kts | 4 +- .../AppServerServiceNameProvider.java | 2 +- .../AppServerServiceNameProviderTest.java | 2 +- samplers/build.gradle.kts | 2 +- .../sampler/LinksBasedSamplerTest.java | 42 +++++++++---------- .../sampler/RuleBasedRoutingSamplerTest.java | 24 +++++------ settings.gradle.kts | 4 -- 23 files changed, 73 insertions(+), 60 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 0f7d57695..4e23aa3c4 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -4,6 +4,16 @@ "config:base" ], "packageRules": [ + { + "matchPackageNames": [ + "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha" + ], + // Renovate's default behavior is only to update from unstable -> unstable if it's for the + // major.minor.patch, under the assumption that you would want to update to the stable version + // of that release instead of the unstable version for a future release (but there's never any + // stable version of opentelemetry-instrumentation-bom-alpha so this logic doesn't apply + "ignoreUnstable": false + }, { "matchPackagePrefixes": ["ch.qos.logback:"], "groupName": "logback packages" diff --git a/aws-resources/build.gradle.kts b/aws-resources/build.gradle.kts index ef911af0d..8e9471c0c 100644 --- a/aws-resources/build.gradle.kts +++ b/aws-resources/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { api("io.opentelemetry:opentelemetry-api") api("io.opentelemetry:opentelemetry-sdk") - implementation("io.opentelemetry:opentelemetry-semconv") + implementation("io.opentelemetry.semconv:opentelemetry-semconv") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java index 17f981674..502a63310 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.File; import java.io.IOException; import java.util.logging.Level; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java index 24f1b3364..73d6517b1 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index dbf8af2e1..badc358f4 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.IOException; import java.util.Collections; import java.util.Locale; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java index fdb4351fb..fc268098a 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/LambdaResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/LambdaResource.java index a3c16ba5f..5bdccd9ab 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/LambdaResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/LambdaResource.java @@ -8,7 +8,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.util.Map; import java.util.stream.Stream; diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/BeanstalkResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/BeanstalkResourceTest.java index 36c6adef9..84d55de2a 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/BeanstalkResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/BeanstalkResourceTest.java @@ -13,7 +13,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.File; import java.io.IOException; import java.util.ServiceLoader; diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/Ec2ResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/Ec2ResourceTest.java index 64f5d2c06..26ce5264f 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/Ec2ResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/Ec2ResourceTest.java @@ -16,7 +16,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.util.ServiceLoader; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java index 16c26f4ae..e822d88b0 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java @@ -14,7 +14,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Collections; diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java index 509be8d9a..7649836bb 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java @@ -18,7 +18,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.io.File; import java.io.IOException; import java.util.ServiceLoader; diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/LambdaResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/LambdaResourceTest.java index e4a35a590..8421ccc7d 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/LambdaResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/LambdaResourceTest.java @@ -13,7 +13,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; diff --git a/aws-xray/build.gradle.kts b/aws-xray/build.gradle.kts index a07bf2b66..ccec9d52f 100644 --- a/aws-xray/build.gradle.kts +++ b/aws-xray/build.gradle.kts @@ -45,3 +45,10 @@ testing { } } } + +configurations.all { + resolutionStrategy { + // TODO this module still needs to be updated to the latest semconv + force("io.opentelemetry:opentelemetry-semconv:1.28.0-alpha") + } +} diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index d70545a80..cc7a86ea6 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -13,7 +13,7 @@ val DEPENDENCY_BOMS = listOf( "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.58.0", - "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.28.0-alpha", + "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.30.0-alpha", "org.testcontainers:testcontainers-bom:1.19.0" ) @@ -46,7 +46,6 @@ val CORE_DEPENDENCIES = listOf( ) val DEPENDENCIES = listOf( - "io.opentelemetry.javaagent:opentelemetry-javaagent:1.30.0", "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.11.0", diff --git a/jmx-metrics/build.gradle.kts b/jmx-metrics/build.gradle.kts index bccd25e1b..94ff15521 100644 --- a/jmx-metrics/build.gradle.kts +++ b/jmx-metrics/build.gradle.kts @@ -19,10 +19,6 @@ repositories { includeGroupByRegex("""org\.terracotta.*""") } } - maven { - url = uri("https://oss.sonatype.org/content/repositories/snapshots") - } - mavenLocal() } val groovyVersion = "3.0.19" diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index b9b480cc7..30316f046 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -60,3 +60,10 @@ tasks { } tasks.getByName("test").dependsOn("shadowJar") + +configurations.all { + resolutionStrategy { + // TODO this module still needs to be updated to the latest semconv + force("io.opentelemetry:opentelemetry-semconv:1.28.0-alpha") + } +} diff --git a/resource-providers/build.gradle.kts b/resource-providers/build.gradle.kts index 67dd47830..0a816d7ae 100644 --- a/resource-providers/build.gradle.kts +++ b/resource-providers/build.gradle.kts @@ -14,9 +14,9 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - compileOnly("io.opentelemetry:opentelemetry-semconv") + compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling") - testImplementation("io.opentelemetry:opentelemetry-semconv") + testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("com.google.auto.service:auto-service") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling") { diff --git a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProvider.java b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProvider.java index c8409f496..0c6f86b6d 100644 --- a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProvider.java +++ b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProvider.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.resourceproviders; -import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; import static java.util.logging.Level.FINE; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; diff --git a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProviderTest.java b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProviderTest.java index 5b501c70f..e4b3957a7 100644 --- a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProviderTest.java +++ b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/AppServerServiceNameProviderTest.java @@ -12,7 +12,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; diff --git a/samplers/build.gradle.kts b/samplers/build.gradle.kts index cef15ca06..38d982496 100644 --- a/samplers/build.gradle.kts +++ b/samplers/build.gradle.kts @@ -8,7 +8,7 @@ otelJava.moduleName.set("io.opentelemetry.contrib.sampler") dependencies { api("io.opentelemetry:opentelemetry-sdk") - api("io.opentelemetry:opentelemetry-semconv") + api("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") } diff --git a/samplers/src/test/java/io/opentelemetry/contrib/sampler/LinksBasedSamplerTest.java b/samplers/src/test/java/io/opentelemetry/contrib/sampler/LinksBasedSamplerTest.java index f3a208f9b..fd46d8134 100644 --- a/samplers/src/test/java/io/opentelemetry/contrib/sampler/LinksBasedSamplerTest.java +++ b/samplers/src/test/java/io/opentelemetry/contrib/sampler/LinksBasedSamplerTest.java @@ -14,17 +14,16 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.trace.IdGenerator; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Test; class LinksBasedSamplerTest { @@ -191,23 +190,22 @@ void testTwoUnsampled() { } @Test - void testProvider() throws Exception { - Method method = - Class.forName("io.opentelemetry.sdk.autoconfigure.TracerProviderConfiguration") - .getDeclaredMethod( - "configureSampler", String.class, ConfigProperties.class, ClassLoader.class); - method.setAccessible(true); - - Sampler sampler = - (Sampler) - method.invoke( - null, - "linksbased_parentbased_always_on", - DefaultConfigProperties.createForTest(Collections.emptyMap()), - AutoConfiguredOpenTelemetrySdkBuilder.class.getClassLoader()); - - assertThat(sampler.getDescription()) - .isEqualTo( - LinksBasedSampler.create(Sampler.parentBased(Sampler.alwaysOn())).getDescription()); + void testProvider() { + Map config = new HashMap<>(); + config.put("otel.traces.exporter", "none"); + config.put("otel.metrics.exporter", "none"); + config.put("otel.logs.exporter", "none"); + config.put("otel.traces.sampler", "linksbased_parentbased_always_on"); + AutoConfiguredOpenTelemetrySdk.builder() + .addPropertiesSupplier(() -> config) + .addSamplerCustomizer( + (sampler, configProperties) -> { + assertThat(sampler.getDescription()) + .isEqualTo( + LinksBasedSampler.create(Sampler.parentBased(Sampler.alwaysOn())) + .getDescription()); + return sampler; + }) + .build(); } } diff --git a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java index 2d11a60ed..6027c6415 100644 --- a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java +++ b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.sampler; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_TARGET; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL; +import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; +import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -57,8 +57,8 @@ public void setup() { when(delegate.shouldSample(any(), any(), any(), any(), any(), any())) .thenReturn(SamplingResult.create(SamplingDecision.RECORD_AND_SAMPLE)); - patterns.add(new SamplingRule(HTTP_URL, ".*/healthcheck", Sampler.alwaysOff())); - patterns.add(new SamplingRule(HTTP_TARGET, "/actuator", Sampler.alwaysOff())); + patterns.add(new SamplingRule(URL_FULL, ".*/healthcheck", Sampler.alwaysOff())); + patterns.add(new SamplingRule(URL_PATH, "/actuator", Sampler.alwaysOff())); } @Test @@ -83,7 +83,7 @@ public void testThatThrowsOnNullParameter() { assertThatExceptionOfType(NullPointerException.class) .isThrownBy( - () -> RuleBasedRoutingSampler.builder(SPAN_KIND, delegate).drop(HTTP_URL, null)); + () -> RuleBasedRoutingSampler.builder(SPAN_KIND, delegate).drop(URL_FULL, null)); assertThatExceptionOfType(NullPointerException.class) .isThrownBy( @@ -93,7 +93,7 @@ public void testThatThrowsOnNullParameter() { .isThrownBy( () -> RuleBasedRoutingSampler.builder(SPAN_KIND, delegate) - .recordAndSample(HTTP_URL, null)); + .recordAndSample(URL_FULL, null)); } @Test @@ -109,7 +109,7 @@ public void testThatDelegatesIfNoRulesGiven() { clearInvocations(delegate); // with http.url attribute - attributes = Attributes.of(HTTP_URL, "https://example.com"); + attributes = Attributes.of(URL_FULL, "https://example.com"); sampler.shouldSample(parentContext, traceId, SPAN_NAME, SPAN_KIND, attributes, emptyList()); verify(delegate) .shouldSample(parentContext, traceId, SPAN_NAME, SPAN_KIND, attributes, emptyList()); @@ -160,7 +160,7 @@ public void testDelegateOnMalformedUrl() { public void testVerifiesAllGivenAttributes() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); - Attributes attributes = Attributes.of(HTTP_TARGET, "/actuator/info"); + Attributes attributes = Attributes.of(URL_PATH, "/actuator/info"); assertThat( sampler .shouldSample(parentContext, traceId, SPAN_NAME, SPAN_KIND, attributes, emptyList()) @@ -170,10 +170,10 @@ public void testVerifiesAllGivenAttributes() { @Test void customSampler() { - Attributes attributes = Attributes.of(HTTP_TARGET, "/test"); + Attributes attributes = Attributes.of(URL_PATH, "/test"); RuleBasedRoutingSampler testSampler = RuleBasedRoutingSampler.builder(SPAN_KIND, delegate) - .customize(HTTP_TARGET, ".*test", new AlternatingSampler()) + .customize(URL_PATH, ".*test", new AlternatingSampler()) .build(); assertThat( testSampler @@ -188,13 +188,13 @@ void customSampler() { } private SamplingResult shouldSample(Sampler sampler, String url) { - Attributes attributes = Attributes.of(HTTP_URL, url); + Attributes attributes = Attributes.of(URL_FULL, url); return sampler.shouldSample( parentContext, traceId, SPAN_NAME, SPAN_KIND, attributes, emptyList()); } private static RuleBasedRoutingSamplerBuilder addRules(RuleBasedRoutingSamplerBuilder builder) { - return builder.drop(HTTP_URL, ".*/healthcheck").drop(HTTP_TARGET, "/actuator"); + return builder.drop(URL_FULL, ".*/healthcheck").drop(URL_PATH, "/actuator"); } /** Silly sampler that alternates decisions for testing. */ diff --git a/settings.gradle.kts b/settings.gradle.kts index 46f8f3d46..97ba5e61e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,10 +13,6 @@ plugins { dependencyResolutionManagement { repositories { mavenCentral() - maven { - url = uri("https://oss.sonatype.org/content/repositories/snapshots") - } - mavenLocal() } } From cecff4e1952588ad0672fcff321c2e74e154c585 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 18 Sep 2023 08:26:57 -0700 Subject: [PATCH 059/108] Add new components to issue templates (#1045) --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 +++ .github/ISSUE_TEMPLATE/feature_request.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e7e2b6c8f..14eb01cdf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -13,14 +13,17 @@ body: - aws-xray - aws-xray-propagator - consistent-sampling + - disk-buffering - jfr-connection - jfr-events - jmx-metrics - maven-extension - micrometer-meter-provider - noop-api + - processors - prometheus-client-bridge - resource-providers + - runtime-attach - samplers - static-instrumenter - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 86569cf22..82da0c388 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -13,14 +13,17 @@ body: - aws-xray - aws-xray-propagator - consistent-sampling + - disk-buffering - jfr-connection - jfr-events - jmx-metrics - maven-extension - micrometer-meter-provider - noop-api + - processors - prometheus-client-bridge - resource-providers + - runtime-attach - samplers - static-instrumenter - type: textarea From 538d860d17beed6bf8c24793bd3b2055c2c58254 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 18 Sep 2023 08:27:49 -0700 Subject: [PATCH 060/108] Remove inactive component owners (#1046) --- .github/component_owners.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/component_owners.yml b/.github/component_owners.yml index b42a6ef5f..930a5141d 100644 --- a/.github/component_owners.yml +++ b/.github/component_owners.yml @@ -25,11 +25,7 @@ components: disk-buffering: - LikeTheSalad - zeitlinger - samplers: - - iNikem - - trask jfr-connection: - - trask - breedx-splk - jeanbisutti - dsgrieve @@ -57,7 +53,8 @@ components: - mateuszrzeszutek - laurit runtime-attach: - - iNikem - jeanbisutti + samplers: + - trask static-instrumenter: - anosek-an From 2acbe763f6cdf38f2abfc5bd4d6f10495336a118 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 18 Sep 2023 08:28:16 -0700 Subject: [PATCH 061/108] Change log for 1.30.0 (#1042) --- .github/scripts/draft-change-log-entries.sh | 1 + CHANGELOG.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh index 94f38b906..55eb299b6 100755 --- a/.github/scripts/draft-change-log-entries.sh +++ b/.github/scripts/draft-change-log-entries.sh @@ -35,6 +35,7 @@ component_names["jmx-metrics/"]="JMX metrics" component_names["maven-extension/"]="Maven extension" component_names["micrometer-meter-provider/"]="Micrometer MeterProvider" component_names["noop-api/"]="No-op API" +component_names["processors/"]="Telemetry processors" component_names["prometheus-client-bridge/"]="Prometheus client bridge" component_names["runtime-attach/"]="Runtime attach" component_names["resource-providers/"]="Resource providers" diff --git a/CHANGELOG.md b/CHANGELOG.md index f06aeb39f..70806228d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## Unreleased +### Disk buffering + +- Remove protobuf dependency + ([#1008](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1008)) + +### Maven extension + +- Disable OTel SDK shutdown hook registration + ([#1022](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1022)) + +### Telemetry processors - New 🌟 + +This module contains tools for globally processing telemetry, including modifying and filtering +telemetry. + ## Version 1.29.0 (2023-08-23) ### Consistent sampling From 0f2112f3cf5253ea307f7fe42c7618107fe62487 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:41:54 -0700 Subject: [PATCH 062/108] Update version to 1.31.0-SNAPSHOT (#1048) --- CHANGELOG.md | 2 ++ version.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70806228d..7f6438e06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## Version 1.30.0 (2023-09-18) + ### Disk buffering - Remove protobuf dependency diff --git a/version.gradle.kts b/version.gradle.kts index a428e3c21..a7e1145a2 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.30.0-SNAPSHOT" -val alphaVersion = "1.30.0-alpha-SNAPSHOT" +val stableVersion = "1.31.0-SNAPSHOT" +val alphaVersion = "1.31.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") { From 0a6184590ff30997b14d72a5331829d792717851 Mon Sep 17 00:00:00 2001 From: Helen <56097766+heyams@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:44:25 -0700 Subject: [PATCH 063/108] Support `thread.name` attributes in RuleBasedRoutingSampler (#1030) Co-authored-by: Trask Stalnaker --- .../contrib/sampler/RuleBasedRoutingSampler.java | 8 +++++++- .../contrib/sampler/RuleBasedRoutingSamplerTest.java | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSampler.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSampler.java index 19f748353..e29ffd3ba 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSampler.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSampler.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.sampler; +import static io.opentelemetry.semconv.SemanticAttributes.THREAD_NAME; import static java.util.Objects.requireNonNull; import io.opentelemetry.api.common.Attributes; @@ -60,7 +61,12 @@ public SamplingResult shouldSample( return fallback.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); } for (SamplingRule samplingRule : rules) { - String attributeValue = attributes.get(samplingRule.attributeKey); + String attributeValue; + if (samplingRule.attributeKey.getKey().equals(THREAD_NAME.getKey())) { + attributeValue = Thread.currentThread().getName(); + } else { + attributeValue = attributes.get(samplingRule.attributeKey); + } if (attributeValue == null) { continue; } diff --git a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java index 6027c6415..30cf25871 100644 --- a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java +++ b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.sampler; +import static io.opentelemetry.semconv.SemanticAttributes.THREAD_NAME; import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; import static java.util.Collections.emptyList; @@ -187,6 +188,16 @@ void customSampler() { .isEqualTo(SamplingDecision.RECORD_AND_SAMPLE); } + @Test + void testThreadNameSampler() { + patterns.add(new SamplingRule(THREAD_NAME, "Test.*", Sampler.alwaysOff())); + Attributes attributes = Attributes.of(THREAD_NAME, "Test worker"); + RuleBasedRoutingSampler sampler = new RuleBasedRoutingSampler(patterns, SPAN_KIND, delegate); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, SPAN_NAME, SPAN_KIND, attributes, emptyList()); + assertThat(samplingResult.getDecision()).isEqualTo(SamplingDecision.DROP); + } + private SamplingResult shouldSample(Sampler sampler, String url) { Attributes attributes = Attributes.of(URL_FULL, url); return sampler.shouldSample( From 5ad1035f544d94747c847d508c50b963ece124fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:44:00 +0000 Subject: [PATCH 064/108] Update errorProneVersion to v2.22.0 (#1052) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Trask Stalnaker --- dependencyManagement/build.gradle.kts | 2 +- .../contrib/staticinstrumenter/test/HttpClientTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index cc7a86ea6..03d4b414f 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -19,7 +19,7 @@ val DEPENDENCY_BOMS = listOf( val autoServiceVersion = "1.1.1" val autoValueVersion = "1.10.4" -val errorProneVersion = "2.21.1" +val errorProneVersion = "2.22.0" val prometheusVersion = "0.16.0" val mockitoVersion = "4.11.0" val slf4jVersion = "2.0.9" diff --git a/static-instrumenter/test-app/src/main/java/io/opentelemetry/contrib/staticinstrumenter/test/HttpClientTest.java b/static-instrumenter/test-app/src/main/java/io/opentelemetry/contrib/staticinstrumenter/test/HttpClientTest.java index 0ebc5483d..c44198e56 100644 --- a/static-instrumenter/test-app/src/main/java/io/opentelemetry/contrib/staticinstrumenter/test/HttpClientTest.java +++ b/static-instrumenter/test-app/src/main/java/io/opentelemetry/contrib/staticinstrumenter/test/HttpClientTest.java @@ -38,6 +38,5 @@ private static void makeCall() throws IOException { } } System.out.println("FAILURE"); - return; } } From 105e50c9d550c16bf9b183cef087668cd2440a94 Mon Sep 17 00:00:00 2001 From: Otmar Ertl Date: Mon, 25 Sep 2023 20:39:00 +0200 Subject: [PATCH 065/108] improved java doc, explicit passing of invalid p-value to root sampler (#1053) --- .../sampler/consistent/ConsistentParentBasedSampler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ConsistentParentBasedSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ConsistentParentBasedSampler.java index 94d70b187..0a3c93c28 100644 --- a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ConsistentParentBasedSampler.java +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent/ConsistentParentBasedSampler.java @@ -10,9 +10,8 @@ import javax.annotation.concurrent.Immutable; /** - * A consistent sampler that makes the same sampling decision as the parent and optionally falls - * back to an alternative consistent sampler, if the parent p-value is invalid (like for root - * spans). + * A consistent sampler that makes the same sampling decision as the parent. For root spans, the + * sampling decision is delegated to the root sampler. */ @Immutable final class ConsistentParentBasedSampler extends ConsistentSampler { @@ -38,7 +37,7 @@ final class ConsistentParentBasedSampler extends ConsistentSampler { @Override protected int getP(int parentP, boolean isRoot) { if (isRoot) { - return rootSampler.getP(parentP, isRoot); + return rootSampler.getP(OtelTraceState.getInvalidP(), isRoot); } else { return parentP; } From 0f74a0180915917e32aa2fcff751fc575d0a2c57 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:51:27 +0000 Subject: [PATCH 066/108] Update plugin com.squareup.wire to v4.9.0 (#1051) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index be2259dbb..5a625ff8a 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -5,7 +5,7 @@ plugins { id("otel.publish-conventions") id("me.champeau.jmh") version "0.7.1" id("ru.vyarus.animalsniffer") version "1.7.1" - id("com.squareup.wire") version "4.8.1" + id("com.squareup.wire") version "4.9.0" } description = "Exporter implementations that store signals on disk" From 1d14305fb02492b185cc813d802b29df0e957a92 Mon Sep 17 00:00:00 2001 From: Dennis Kieselhorst Date: Tue, 26 Sep 2023 20:50:54 +0200 Subject: [PATCH 067/108] Move to io.opentelemetry.semconv:opentelemetry-semconv (#1050) --- aws-xray/build.gradle.kts | 9 +- .../awsxray/AwsMetricAttributeGenerator.java | 76 ++++++++-------- .../awsxray/AwsSpanMetricsProcessor.java | 4 +- .../contrib/awsxray/SamplingRuleApplier.java | 18 +++- .../AwsMetricAttributeGeneratorTest.java | 90 +++++++++---------- .../awsxray/AwsSpanMetricsProcessorTest.java | 12 +-- .../AwsXrayRemoteSamplerProviderTest.java | 2 +- .../awsxray/SamplingRuleApplierTest.java | 88 +++++++++--------- 8 files changed, 152 insertions(+), 147 deletions(-) diff --git a/aws-xray/build.gradle.kts b/aws-xray/build.gradle.kts index ccec9d52f..bfbb14504 100644 --- a/aws-xray/build.gradle.kts +++ b/aws-xray/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") implementation("com.squareup.okhttp3:okhttp") - implementation("io.opentelemetry:opentelemetry-semconv") + implementation("io.opentelemetry.semconv:opentelemetry-semconv") annotationProcessor("com.google.auto.service:auto-service") testImplementation("com.google.auto.service:auto-service") @@ -45,10 +45,3 @@ testing { } } } - -configurations.all { - resolutionStrategy { - // TODO this module still needs to be updated to the latest semconv - force("io.opentelemetry:opentelemetry-semconv:1.28.0-alpha") - } -} diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java index bf55d061e..69f2e63a3 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java @@ -15,24 +15,24 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_SPAN_KIND; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; -import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SYSTEM; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_TRIGGER; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.GRAPHQL_OPERATION_TYPE; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_METHOD; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_TARGET; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_OPERATION; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_SYSTEM; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_ADDR; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_PORT; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.PEER_SERVICE; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_METHOD; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_SERVICE; +import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.SemanticAttributes.DB_SYSTEM; +import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_NAME; +import static io.opentelemetry.semconv.SemanticAttributes.FAAS_TRIGGER; +import static io.opentelemetry.semconv.SemanticAttributes.GRAPHQL_OPERATION_TYPE; +import static io.opentelemetry.semconv.SemanticAttributes.HTTP_REQUEST_METHOD; +import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_OPERATION; +import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_SYSTEM; +import static io.opentelemetry.semconv.SemanticAttributes.PEER_SERVICE; +import static io.opentelemetry.semconv.SemanticAttributes.RPC_METHOD; +import static io.opentelemetry.semconv.SemanticAttributes.RPC_SERVICE; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_ADDRESS; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_PORT; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_ADDRESS; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_PORT; +import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; +import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -40,8 +40,8 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import io.opentelemetry.semconv.ResourceAttributes; +import io.opentelemetry.semconv.SemanticAttributes; import java.net.MalformedURLException; import java.net.URL; import java.util.Optional; @@ -156,8 +156,8 @@ private static boolean isValidOperation(SpanData span) { if (operation == null || operation.equals(UNKNOWN_OPERATION)) { return false; } - if (isKeyPresent(span, HTTP_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_METHOD); + if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); return !operation.equals(httpMethod); } return true; @@ -260,15 +260,15 @@ private static void setRemoteServiceAndOperation(SpanData span, AttributesBuilde */ private static String generateIngressOperation(SpanData span) { String operation = UNKNOWN_OPERATION; - if (isKeyPresent(span, HTTP_TARGET)) { - String httpTarget = span.getAttributes().get(HTTP_TARGET); + if (isKeyPresent(span, URL_PATH)) { + String httpTarget = span.getAttributes().get(URL_PATH); // get the first part from API path string as operation value // the more levels/parts we get from API path the higher chance for getting high cardinality // data if (httpTarget != null) { operation = extractApiPathValue(httpTarget); - if (isKeyPresent(span, HTTP_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_METHOD); + if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); if (httpMethod != null) { operation = httpMethod + " " + operation; } @@ -284,8 +284,8 @@ private static String generateIngressOperation(SpanData span) { */ private static String generateRemoteOperation(SpanData span) { String remoteOperation = UNKNOWN_REMOTE_OPERATION; - if (isKeyPresent(span, HTTP_URL)) { - String httpUrl = span.getAttributes().get(HTTP_URL); + if (isKeyPresent(span, URL_FULL)) { + String httpUrl = span.getAttributes().get(URL_FULL); try { URL url; if (httpUrl != null) { @@ -296,8 +296,8 @@ private static String generateRemoteOperation(SpanData span) { logger.log(Level.FINEST, "invalid http.url attribute: ", httpUrl); } } - if (isKeyPresent(span, HTTP_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_METHOD); + if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); remoteOperation = httpMethod + " " + remoteOperation; } if (remoteOperation.equals(UNKNOWN_REMOTE_OPERATION)) { @@ -325,16 +325,16 @@ private static String extractApiPathValue(String httpTarget) { private static String generateRemoteService(SpanData span) { String remoteService = UNKNOWN_REMOTE_SERVICE; - if (isKeyPresent(span, NET_PEER_NAME)) { - remoteService = getRemoteService(span, NET_PEER_NAME); - if (isKeyPresent(span, NET_PEER_PORT)) { - Long port = span.getAttributes().get(NET_PEER_PORT); + if (isKeyPresent(span, SERVER_ADDRESS)) { + remoteService = getRemoteService(span, SERVER_ADDRESS); + if (isKeyPresent(span, SERVER_PORT)) { + Long port = span.getAttributes().get(SERVER_PORT); remoteService += ":" + port; } - } else if (isKeyPresent(span, NET_SOCK_PEER_ADDR)) { - remoteService = getRemoteService(span, NET_SOCK_PEER_ADDR); - if (isKeyPresent(span, NET_SOCK_PEER_PORT)) { - Long port = span.getAttributes().get(NET_SOCK_PEER_PORT); + } else if (isKeyPresent(span, SERVER_SOCKET_ADDRESS)) { + remoteService = getRemoteService(span, SERVER_SOCKET_ADDRESS); + if (isKeyPresent(span, SERVER_SOCKET_PORT)) { + Long port = span.getAttributes().get(SERVER_SOCKET_PORT); remoteService += ":" + port; } } else { diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java index fb2c2a103..7dec5d0ac 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_STATUS_CODE; +import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; @@ -107,7 +107,7 @@ public boolean isEndRequired() { } private void recordErrorOrFault(SpanData spanData, Attributes attributes) { - Long httpStatusCode = spanData.getAttributes().get(HTTP_STATUS_CODE); + Long httpStatusCode = spanData.getAttributes().get(HTTP_RESPONSE_STATUS_CODE); if (httpStatusCode == null) { httpStatusCode = getAwsStatusCode(spanData); diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java index 1ef8abf50..5f3d9a8bc 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java @@ -17,8 +17,8 @@ import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import io.opentelemetry.semconv.ResourceAttributes; +import io.opentelemetry.semconv.SemanticAttributes; import java.time.Duration; import java.util.Collections; import java.util.Date; @@ -162,13 +162,25 @@ boolean matches(Attributes attributes, Resource resource) { String host = null; for (Map.Entry, Object> entry : attributes.asMap().entrySet()) { - if (entry.getKey().equals(SemanticAttributes.HTTP_TARGET)) { + if (entry.getKey().equals(SemanticAttributes.URL_PATH)) { httpTarget = (String) entry.getValue(); + } else if (entry.getKey().equals(SemanticAttributes.HTTP_TARGET)) { + // TODO remove support for deprecated http.target attribute + httpTarget = (String) entry.getValue(); + } else if (entry.getKey().equals(SemanticAttributes.URL_FULL)) { + httpUrl = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_URL)) { + // TODO remove support for deprecated http.url attribute httpUrl = (String) entry.getValue(); + } else if (entry.getKey().equals(SemanticAttributes.HTTP_REQUEST_METHOD)) { + httpMethod = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_METHOD)) { + // TODO remove support for deprecated http.method attribute httpMethod = (String) entry.getValue(); + } else if (entry.getKey().equals(SemanticAttributes.SERVER_ADDRESS)) { + host = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.NET_HOST_NAME)) { + // TODO remove support for deprecated net.host.name attribute host = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_HOST)) { // TODO (trask) remove support for deprecated http.host attribute diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java index b1df48daa..256be20ac 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java @@ -15,25 +15,25 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_SPAN_KIND; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; -import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SYSTEM; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_PROVIDER; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_TRIGGER; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.GRAPHQL_OPERATION_TYPE; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_METHOD; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_TARGET; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_OPERATION; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_SYSTEM; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_ADDR; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_PORT; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.PEER_SERVICE; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_METHOD; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_SERVICE; +import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.SemanticAttributes.DB_SYSTEM; +import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_NAME; +import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_PROVIDER; +import static io.opentelemetry.semconv.SemanticAttributes.FAAS_TRIGGER; +import static io.opentelemetry.semconv.SemanticAttributes.GRAPHQL_OPERATION_TYPE; +import static io.opentelemetry.semconv.SemanticAttributes.HTTP_REQUEST_METHOD; +import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_OPERATION; +import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_SYSTEM; +import static io.opentelemetry.semconv.SemanticAttributes.PEER_SERVICE; +import static io.opentelemetry.semconv.SemanticAttributes.RPC_METHOD; +import static io.opentelemetry.semconv.SemanticAttributes.RPC_SERVICE; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_ADDRESS; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_PORT; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_ADDRESS; +import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_PORT; +import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; +import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -170,7 +170,7 @@ public void testServerSpanWithNullSpanName() { public void testServerSpanWithSpanNameAsHttpMethod() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("GET"); - mockAttribute(HTTP_METHOD, "GET"); + mockAttribute(HTTP_REQUEST_METHOD, "GET"); Attributes expectedAttributes = Attributes.of( @@ -178,15 +178,15 @@ public void testServerSpanWithSpanNameAsHttpMethod() { AWS_LOCAL_SERVICE, SERVICE_NAME_VALUE, AWS_LOCAL_OPERATION, UNKNOWN_OPERATION); validateAttributesProducedForSpanOfKind(expectedAttributes, SpanKind.SERVER); - mockAttribute(HTTP_METHOD, null); + mockAttribute(HTTP_REQUEST_METHOD, null); } @Test public void testServerSpanWithSpanNameWithHttpTarget() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("POST"); - mockAttribute(HTTP_METHOD, "POST"); - mockAttribute(HTTP_TARGET, "/payment/123"); + mockAttribute(HTTP_REQUEST_METHOD, "POST"); + mockAttribute(URL_PATH, "/payment/123"); Attributes expectedAttributes = Attributes.of( @@ -197,8 +197,8 @@ public void testServerSpanWithSpanNameWithHttpTarget() { AWS_LOCAL_OPERATION, "POST /payment"); validateAttributesProducedForSpanOfKind(expectedAttributes, SpanKind.SERVER); - mockAttribute(HTTP_METHOD, null); - mockAttribute(HTTP_TARGET, null); + mockAttribute(HTTP_REQUEST_METHOD, null); + mockAttribute(URL_PATH, null); } @Test @@ -283,44 +283,44 @@ public void testRemoteAttributesCombinations() { mockAttribute(GRAPHQL_OPERATION_TYPE, null); // Validate behaviour of extracting Remote Service from net.peer.name - mockAttribute(NET_PEER_NAME, "www.example.com"); + mockAttribute(SERVER_ADDRESS, "www.example.com"); validateExpectedRemoteAttributes("www.example.com", UNKNOWN_REMOTE_OPERATION); - mockAttribute(NET_PEER_NAME, null); + mockAttribute(SERVER_ADDRESS, null); // Validate behaviour of extracting Remote Service from net.peer.name and net.peer.port - mockAttribute(NET_PEER_NAME, "192.168.0.0"); - mockAttribute(NET_PEER_PORT, 8081L); + mockAttribute(SERVER_ADDRESS, "192.168.0.0"); + mockAttribute(SERVER_PORT, 8081L); validateExpectedRemoteAttributes("192.168.0.0:8081", UNKNOWN_REMOTE_OPERATION); - mockAttribute(NET_PEER_NAME, null); - mockAttribute(NET_PEER_PORT, null); + mockAttribute(SERVER_ADDRESS, null); + mockAttribute(SERVER_PORT, null); // Validate behaviour of extracting Remote Service from net.peer.socket.addr - mockAttribute(NET_SOCK_PEER_ADDR, "www.example.com"); + mockAttribute(SERVER_SOCKET_ADDRESS, "www.example.com"); validateExpectedRemoteAttributes("www.example.com", UNKNOWN_REMOTE_OPERATION); - mockAttribute(NET_SOCK_PEER_ADDR, null); + mockAttribute(SERVER_SOCKET_ADDRESS, null); // Validate behaviour of extracting Remote Service from net.peer.socket.addr and // net.sock.peer.port - mockAttribute(NET_SOCK_PEER_ADDR, "192.168.0.0"); - mockAttribute(NET_SOCK_PEER_PORT, 8081L); + mockAttribute(SERVER_SOCKET_ADDRESS, "192.168.0.0"); + mockAttribute(SERVER_SOCKET_PORT, 8081L); validateExpectedRemoteAttributes("192.168.0.0:8081", UNKNOWN_REMOTE_OPERATION); - mockAttribute(NET_SOCK_PEER_ADDR, null); - mockAttribute(NET_SOCK_PEER_PORT, null); + mockAttribute(SERVER_SOCKET_ADDRESS, null); + mockAttribute(SERVER_SOCKET_PORT, null); // Validate behavior of Remote Operation from HttpTarget - with 1st api part, then remove it - mockAttribute(HTTP_URL, "http://www.example.com/payment/123"); + mockAttribute(URL_FULL, "http://www.example.com/payment/123"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, "/payment"); - mockAttribute(HTTP_URL, null); + mockAttribute(URL_FULL, null); // Validate behavior of Remote Operation from HttpTarget - without 1st api part, then remove it - mockAttribute(HTTP_URL, "http://www.example.com"); + mockAttribute(URL_FULL, "http://www.example.com"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, "/"); - mockAttribute(HTTP_URL, null); + mockAttribute(URL_FULL, null); // Validate behavior of Remote Operation from HttpTarget - invalid url, then remove it - mockAttribute(HTTP_URL, "abc"); + mockAttribute(URL_FULL, "abc"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, UNKNOWN_REMOTE_OPERATION); - mockAttribute(HTTP_URL, null); + mockAttribute(URL_FULL, null); // Validate behaviour of Peer service attribute, then remove it. mockAttribute(PEER_SERVICE, "Peer service"); @@ -338,8 +338,8 @@ public void testPeerServiceDoesOverrideOtherRemoteServices() { validatePeerServiceDoesOverride(FAAS_INVOKED_PROVIDER); validatePeerServiceDoesOverride(MESSAGING_SYSTEM); validatePeerServiceDoesOverride(GRAPHQL_OPERATION_TYPE); - validatePeerServiceDoesOverride(NET_PEER_NAME); - validatePeerServiceDoesOverride(NET_SOCK_PEER_ADDR); + validatePeerServiceDoesOverride(SERVER_ADDRESS); + validatePeerServiceDoesOverride(SERVER_SOCKET_ADDRESS); // Actually testing that peer service overrides "UnknownRemoteService". validatePeerServiceDoesOverride(AttributeKey.stringKey("unknown.service.key")); } diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java index c2109b267..77188a606 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_STATUS_CODE; +import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -141,7 +141,7 @@ public void testOnEndMetricsGenerationWithoutSpanAttributes() { @Test public void testOnEndMetricsGenerationWithoutMetricAttributes() { - Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); + Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -154,7 +154,7 @@ public void testOnEndMetricsGenerationWithoutMetricAttributes() { @Test public void testOnEndMetricsGenerationWithoutEndRequired() { - Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); + Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -167,7 +167,7 @@ public void testOnEndMetricsGenerationWithoutEndRequired() { @Test public void testOnEndMetricsGenerationWithLatency() { - Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 200L); + Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 200L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -245,7 +245,7 @@ private static ReadableSpan buildReadableSpanMock(Attributes spanAttributes) { private static ReadableSpan buildReadableSpanWithThrowableMock(Throwable throwable) { // config http status code as null - Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, null); + Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, null); ReadableSpan readableSpanMock = mock(ReadableSpan.class); SpanData mockSpanData = mock(SpanData.class); InstrumentationScopeInfo awsSdkScopeInfo = @@ -280,7 +280,7 @@ private void configureMocksForOnEnd(ReadableSpan readableSpanMock, Attributes me private void validateMetricsGeneratedForHttpStatusCode( Long httpStatusCode, ExpectedStatusMetric expectedStatusMetric) { - Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, httpStatusCode); + Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, httpStatusCode); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java index 5a51318f2..046b7cd11 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.ResourceAttributes; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java index 6bb6e82a4..e783c5a10 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -22,8 +22,8 @@ import io.opentelemetry.sdk.testing.time.TestClock; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import io.opentelemetry.semconv.ResourceAttributes; +import io.opentelemetry.semconv.SemanticAttributes; import java.io.IOException; import java.io.UncheckedIOException; import java.time.Duration; @@ -61,9 +61,9 @@ class ExactMatch { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_METHOD, "GET") - .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") - .put(SemanticAttributes.HTTP_TARGET, "/instrument-me") + .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") + .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") + .put(SemanticAttributes.URL_PATH, "/instrument-me") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); @@ -109,8 +109,8 @@ void matches() { assertThat( applier.matches( attributes.toBuilder() - .remove(SemanticAttributes.HTTP_TARGET) - .put(SemanticAttributes.HTTP_URL, "scheme://host:port/instrument-me") + .remove(SemanticAttributes.URL_PATH) + .put(SemanticAttributes.URL_FULL, "scheme://host:port/instrument-me") .build(), resource)) .isTrue(); @@ -133,7 +133,7 @@ void serviceNameNullNotMatch() { @Test void methodNotMatch() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "POST").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "POST").build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -143,7 +143,7 @@ void hostNotMatch() { // wildcard. Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentelemetryfio") + .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetryfio") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -151,20 +151,18 @@ void hostNotMatch() { @Test void pathNotMatch() { Attributes attributes = - this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_TARGET, "/instrument-you") - .build(); + this.attributes.toBuilder().put(SemanticAttributes.URL_PATH, "/instrument-you").build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.HTTP_TARGET) - .put(SemanticAttributes.HTTP_URL, "scheme://host:port/instrument-you") + .remove(SemanticAttributes.URL_PATH) + .put(SemanticAttributes.URL_FULL, "scheme://host:port/instrument-you") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.HTTP_TARGET) - .put(SemanticAttributes.HTTP_URL, "scheme://host:port") + .remove(SemanticAttributes.URL_PATH) + .put(SemanticAttributes.URL_FULL, "scheme://host:port") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); @@ -172,8 +170,8 @@ void pathNotMatch() { // present. attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.HTTP_TARGET) - .put(SemanticAttributes.HTTP_URL, "host:port/instrument-me") + .remove(SemanticAttributes.URL_PATH) + .put(SemanticAttributes.URL_FULL, "host:port/instrument-me") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -236,9 +234,9 @@ class WildcardMatch { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_METHOD, "GET") - .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") - .put(SemanticAttributes.HTTP_TARGET, "/instrument-me?foo=bar&cat=meow") + .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") + .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") + .put(SemanticAttributes.URL_PATH, "/instrument-me?foo=bar&cat=meow") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); @@ -310,22 +308,24 @@ void serviceNameNotMatch() { @Test void methodMatches() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "BADGETGOOD").build(); + this.attributes.toBuilder() + .put(SemanticAttributes.HTTP_REQUEST_METHOD, "BADGETGOOD") + .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "BADGET").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "BADGET").build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "GETGET").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "GETGET").build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @Test void methodNotMatch() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "POST").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "POST").build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_METHOD); + attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_REQUEST_METHOD); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -333,27 +333,27 @@ void methodNotMatch() { void hostMatches() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "alpha.opentelemetry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "alpha.opentelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opfdnqtelemetry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "opfdnqtelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentglemetry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "opentglemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentglemry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "opentglemry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentglemrz.io") + .put(SemanticAttributes.SERVER_ADDRESS, "opentglemrz.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @@ -362,20 +362,20 @@ void hostMatches() { void hostNotMatch() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentelemetryfio") + .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetryfio") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "opentgalemetry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "opentgalemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.NET_HOST_NAME, "alpha.oentelemetry.io") + .put(SemanticAttributes.SERVER_ADDRESS, "alpha.oentelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.NET_HOST_NAME); + attributes = removeAttribute(this.attributes, SemanticAttributes.SERVER_ADDRESS); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -383,13 +383,13 @@ void hostNotMatch() { void pathMatches() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_TARGET, "/instrument-me?foo=bar&cat=") + .put(SemanticAttributes.URL_PATH, "/instrument-me?foo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); // Deceptive question mark, it's actually a wildcard :-) attributes = this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_TARGET, "/instrument-meafoo=bar&cat=") + .put(SemanticAttributes.URL_PATH, "/instrument-meafoo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @@ -398,15 +398,15 @@ void pathMatches() { void pathNotMatch() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_TARGET, "/instrument-mea?foo=bar&cat=") + .put(SemanticAttributes.URL_PATH, "/instrument-mea?foo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_TARGET, "foo/instrument-meafoo=bar&cat=") + .put(SemanticAttributes.URL_PATH, "foo/instrument-meafoo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_TARGET); + attributes = removeAttribute(this.attributes, SemanticAttributes.URL_PATH); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -507,9 +507,9 @@ class AwsLambdaTest { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_METHOD, "GET") - .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") - .put(SemanticAttributes.HTTP_TARGET, "/instrument-me") + .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") + .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") + .put(SemanticAttributes.URL_PATH, "/instrument-me") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); From 9f8ff361a1074ff8dae68392f3400559771d90bb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 08:21:04 -0700 Subject: [PATCH 068/108] Update plugin com.squareup.wire to v4.9.1 (#1054) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 5a625ff8a..86f13f37a 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -5,7 +5,7 @@ plugins { id("otel.publish-conventions") id("me.champeau.jmh") version "0.7.1" id("ru.vyarus.animalsniffer") version "1.7.1" - id("com.squareup.wire") version "4.9.0" + id("com.squareup.wire") version "4.9.1" } description = "Exporter implementations that store signals on disk" From 30492bff7fece65e16a6e49df8aa6ee308d90e34 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:08:19 -0700 Subject: [PATCH 069/108] Update dependency org.testcontainers:testcontainers-bom to v1.19.1 (#1062) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 03d4b414f..f2c4baaa9 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -14,7 +14,7 @@ val DEPENDENCY_BOMS = listOf( "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.58.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.30.0-alpha", - "org.testcontainers:testcontainers-bom:1.19.0" + "org.testcontainers:testcontainers-bom:1.19.1" ) val autoServiceVersion = "1.1.1" From ba896e1e0bcef693ce31723b84c7ae591ff3813b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:21:52 -0700 Subject: [PATCH 070/108] Update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.22.0 (#1057) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Trask Stalnaker --- buildSrc/build.gradle.kts | 2 +- static-instrumenter/agent-instrumenter/build.gradle.kts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 306e62c30..7cb7de38a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,7 @@ repositories { dependencies { // When updating, update above in plugins too - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.21.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.22.0") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.15") diff --git a/static-instrumenter/agent-instrumenter/build.gradle.kts b/static-instrumenter/agent-instrumenter/build.gradle.kts index e0671c521..eee36f9d1 100644 --- a/static-instrumenter/agent-instrumenter/build.gradle.kts +++ b/static-instrumenter/agent-instrumenter/build.gradle.kts @@ -142,6 +142,5 @@ class AgentJarsProvider( @PathSensitive(PathSensitivity.RELATIVE) val noInstAgentJar: Provider, ) : CommandLineArgumentProvider { - override fun asArguments(): Iterable = - listOf("-Dagent=${file(agentJar).path}", "-Dno.inst.agent=${file(noInstAgentJar).path}") + override fun asArguments(): Iterable = listOf("-Dagent=${file(agentJar).path}", "-Dno.inst.agent=${file(noInstAgentJar).path}") } From 7ea1ef85076fffd41005347ab96f265dce6ab4a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 19:37:40 -0700 Subject: [PATCH 071/108] Update dependency net.bytebuddy:byte-buddy-agent to v1.14.9 (#1068) --- runtime-attach/runtime-attach-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-attach/runtime-attach-core/build.gradle.kts b/runtime-attach/runtime-attach-core/build.gradle.kts index 71314c7b4..f7840c1a3 100644 --- a/runtime-attach/runtime-attach-core/build.gradle.kts +++ b/runtime-attach/runtime-attach-core/build.gradle.kts @@ -7,7 +7,7 @@ description = "To help in create an OpenTelemetry distro able to runtime attach otelJava.moduleName.set("io.opentelemetry.contrib.attach.core") dependencies { - implementation("net.bytebuddy:byte-buddy-agent:1.14.8") + implementation("net.bytebuddy:byte-buddy-agent:1.14.9") // Used by byte-buddy but not brought in as a transitive dependency. compileOnly("com.google.code.findbugs:annotations") From b4fbdf6cf7f692cf00416907a08b58218204de48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:35:08 +0200 Subject: [PATCH 072/108] Update micrometer packages to v1.11.5 (#1069) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index e73ce74c4..c717bb03d 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -19,14 +19,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.11.4") + testImplementation("io.micrometer:micrometer-core:1.11.5") } testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.11.4") + implementation("io.micrometer:micrometer-registry-prometheus:1.11.5") } } } From b9be6693c1737f3eab1543e851b215c47b32a3c7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:13:43 -0700 Subject: [PATCH 073/108] Update dependency org.hipparchus:hipparchus-stat to v3 (#1067) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- consistent-sampling/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index 65f9fc25e..f29c32eda 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -10,5 +10,5 @@ dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") testImplementation("org.hipparchus:hipparchus-core:2.3") - testImplementation("org.hipparchus:hipparchus-stat:2.3") + testImplementation("org.hipparchus:hipparchus-stat:3.0") } From 0639f512065ec397f15317e15ebcd7010c2a1ef5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:15:39 -0700 Subject: [PATCH 074/108] Update gradle enterprise packages to v3.15.1 (#1065) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- settings.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7cb7de38a..8d341879c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.22.0") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") - implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.15") + implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.15.1") } spotless { diff --git a/settings.gradle.kts b/settings.gradle.kts index 97ba5e61e..dcd8914b5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ pluginManagement { plugins { id("com.github.johnrengelman.shadow") version "8.1.1" - id("com.gradle.enterprise") version "3.15" + id("com.gradle.enterprise") version "3.15.1" id("io.github.gradle-nexus.publish-plugin") version "1.3.0" } } From 9e372c06dcddc9621cf414798fb646ab3b6a7d3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:16:05 +0000 Subject: [PATCH 075/108] Update dependency org.hipparchus:hipparchus-core to v3 (#1066) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- consistent-sampling/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index f29c32eda..b6700f1ff 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -9,6 +9,6 @@ otelJava.moduleName.set("io.opentelemetry.contrib.sampler.consistent") dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - testImplementation("org.hipparchus:hipparchus-core:2.3") + testImplementation("org.hipparchus:hipparchus-core:3.0") testImplementation("org.hipparchus:hipparchus-stat:3.0") } From acbeb1c842833d2f2c6ab659b8bfed8be44441d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:16:13 -0700 Subject: [PATCH 076/108] Update dependency gradle to v8.4 (#1064) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 864d6c475..46671acb6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=591855b517fc635b9e04de1d05d5e76ada3f89f5fc76f87978d1b245b4f69225 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a5..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ From f0f9abb12a3ab54b8145a5802201492c24e09842 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:09:54 -0700 Subject: [PATCH 077/108] Update dependency com.google.guava:guava-bom to v32.1.3-jre (#1071) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index f2c4baaa9..d4208ac41 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -9,7 +9,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.2", - "com.google.guava:guava-bom:32.1.2-jre", + "com.google.guava:guava-bom:32.1.3-jre", "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.58.0", From 7f1560254eac36b3d5e25af1439c14a21c3f3d4d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:10:24 -0700 Subject: [PATCH 078/108] Update plugin com.diffplug.spotless to v6.22.0 (#1058) Co-authored-by: renovate[bot] <29139614+renovate[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 8d341879c..d84f44f0f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `kotlin-dsl` // When updating, update below in dependencies too - id("com.diffplug.spotless") version "6.21.0" + id("com.diffplug.spotless") version "6.22.0" } repositories { From 8b223f8abe8a84e64ee52a23da6e9fe020180b99 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 13 Oct 2023 09:41:37 -0700 Subject: [PATCH 079/108] Revert "Move to io.opentelemetry.semconv:opentelemetry-semconv (#1050)" (#1070) --- aws-xray/build.gradle.kts | 9 +- .../awsxray/AwsMetricAttributeGenerator.java | 76 ++++++++-------- .../awsxray/AwsSpanMetricsProcessor.java | 4 +- .../contrib/awsxray/SamplingRuleApplier.java | 18 +--- .../AwsMetricAttributeGeneratorTest.java | 90 +++++++++---------- .../awsxray/AwsSpanMetricsProcessorTest.java | 12 +-- .../AwsXrayRemoteSamplerProviderTest.java | 2 +- .../awsxray/SamplingRuleApplierTest.java | 88 +++++++++--------- 8 files changed, 147 insertions(+), 152 deletions(-) diff --git a/aws-xray/build.gradle.kts b/aws-xray/build.gradle.kts index bfbb14504..ccec9d52f 100644 --- a/aws-xray/build.gradle.kts +++ b/aws-xray/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") implementation("com.squareup.okhttp3:okhttp") - implementation("io.opentelemetry.semconv:opentelemetry-semconv") + implementation("io.opentelemetry:opentelemetry-semconv") annotationProcessor("com.google.auto.service:auto-service") testImplementation("com.google.auto.service:auto-service") @@ -45,3 +45,10 @@ testing { } } } + +configurations.all { + resolutionStrategy { + // TODO this module still needs to be updated to the latest semconv + force("io.opentelemetry:opentelemetry-semconv:1.28.0-alpha") + } +} diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java index 69f2e63a3..bf55d061e 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java @@ -15,24 +15,24 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_SPAN_KIND; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; -import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; -import static io.opentelemetry.semconv.SemanticAttributes.DB_OPERATION; -import static io.opentelemetry.semconv.SemanticAttributes.DB_SYSTEM; -import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_NAME; -import static io.opentelemetry.semconv.SemanticAttributes.FAAS_TRIGGER; -import static io.opentelemetry.semconv.SemanticAttributes.GRAPHQL_OPERATION_TYPE; -import static io.opentelemetry.semconv.SemanticAttributes.HTTP_REQUEST_METHOD; -import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_OPERATION; -import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_SYSTEM; -import static io.opentelemetry.semconv.SemanticAttributes.PEER_SERVICE; -import static io.opentelemetry.semconv.SemanticAttributes.RPC_METHOD; -import static io.opentelemetry.semconv.SemanticAttributes.RPC_SERVICE; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_ADDRESS; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_PORT; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_ADDRESS; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_PORT; -import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; -import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SYSTEM; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_TRIGGER; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.GRAPHQL_OPERATION_TYPE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_METHOD; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_TARGET; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_SYSTEM; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_ADDR; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_PORT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.PEER_SERVICE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_METHOD; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_SERVICE; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -40,8 +40,8 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.semconv.ResourceAttributes; -import io.opentelemetry.semconv.SemanticAttributes; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.net.MalformedURLException; import java.net.URL; import java.util.Optional; @@ -156,8 +156,8 @@ private static boolean isValidOperation(SpanData span) { if (operation == null || operation.equals(UNKNOWN_OPERATION)) { return false; } - if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); + if (isKeyPresent(span, HTTP_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_METHOD); return !operation.equals(httpMethod); } return true; @@ -260,15 +260,15 @@ private static void setRemoteServiceAndOperation(SpanData span, AttributesBuilde */ private static String generateIngressOperation(SpanData span) { String operation = UNKNOWN_OPERATION; - if (isKeyPresent(span, URL_PATH)) { - String httpTarget = span.getAttributes().get(URL_PATH); + if (isKeyPresent(span, HTTP_TARGET)) { + String httpTarget = span.getAttributes().get(HTTP_TARGET); // get the first part from API path string as operation value // the more levels/parts we get from API path the higher chance for getting high cardinality // data if (httpTarget != null) { operation = extractApiPathValue(httpTarget); - if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); + if (isKeyPresent(span, HTTP_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_METHOD); if (httpMethod != null) { operation = httpMethod + " " + operation; } @@ -284,8 +284,8 @@ private static String generateIngressOperation(SpanData span) { */ private static String generateRemoteOperation(SpanData span) { String remoteOperation = UNKNOWN_REMOTE_OPERATION; - if (isKeyPresent(span, URL_FULL)) { - String httpUrl = span.getAttributes().get(URL_FULL); + if (isKeyPresent(span, HTTP_URL)) { + String httpUrl = span.getAttributes().get(HTTP_URL); try { URL url; if (httpUrl != null) { @@ -296,8 +296,8 @@ private static String generateRemoteOperation(SpanData span) { logger.log(Level.FINEST, "invalid http.url attribute: ", httpUrl); } } - if (isKeyPresent(span, HTTP_REQUEST_METHOD)) { - String httpMethod = span.getAttributes().get(HTTP_REQUEST_METHOD); + if (isKeyPresent(span, HTTP_METHOD)) { + String httpMethod = span.getAttributes().get(HTTP_METHOD); remoteOperation = httpMethod + " " + remoteOperation; } if (remoteOperation.equals(UNKNOWN_REMOTE_OPERATION)) { @@ -325,16 +325,16 @@ private static String extractApiPathValue(String httpTarget) { private static String generateRemoteService(SpanData span) { String remoteService = UNKNOWN_REMOTE_SERVICE; - if (isKeyPresent(span, SERVER_ADDRESS)) { - remoteService = getRemoteService(span, SERVER_ADDRESS); - if (isKeyPresent(span, SERVER_PORT)) { - Long port = span.getAttributes().get(SERVER_PORT); + if (isKeyPresent(span, NET_PEER_NAME)) { + remoteService = getRemoteService(span, NET_PEER_NAME); + if (isKeyPresent(span, NET_PEER_PORT)) { + Long port = span.getAttributes().get(NET_PEER_PORT); remoteService += ":" + port; } - } else if (isKeyPresent(span, SERVER_SOCKET_ADDRESS)) { - remoteService = getRemoteService(span, SERVER_SOCKET_ADDRESS); - if (isKeyPresent(span, SERVER_SOCKET_PORT)) { - Long port = span.getAttributes().get(SERVER_SOCKET_PORT); + } else if (isKeyPresent(span, NET_SOCK_PEER_ADDR)) { + remoteService = getRemoteService(span, NET_SOCK_PEER_ADDR); + if (isKeyPresent(span, NET_SOCK_PEER_PORT)) { + Long port = span.getAttributes().get(NET_SOCK_PEER_PORT); remoteService += ":" + port; } } else { diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java index 7dec5d0ac..fb2c2a103 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_STATUS_CODE; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; @@ -107,7 +107,7 @@ public boolean isEndRequired() { } private void recordErrorOrFault(SpanData spanData, Attributes attributes) { - Long httpStatusCode = spanData.getAttributes().get(HTTP_RESPONSE_STATUS_CODE); + Long httpStatusCode = spanData.getAttributes().get(HTTP_STATUS_CODE); if (httpStatusCode == null) { httpStatusCode = getAwsStatusCode(spanData); diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java index 5f3d9a8bc..1ef8abf50 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java @@ -17,8 +17,8 @@ import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import io.opentelemetry.semconv.ResourceAttributes; -import io.opentelemetry.semconv.SemanticAttributes; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.time.Duration; import java.util.Collections; import java.util.Date; @@ -162,25 +162,13 @@ boolean matches(Attributes attributes, Resource resource) { String host = null; for (Map.Entry, Object> entry : attributes.asMap().entrySet()) { - if (entry.getKey().equals(SemanticAttributes.URL_PATH)) { + if (entry.getKey().equals(SemanticAttributes.HTTP_TARGET)) { httpTarget = (String) entry.getValue(); - } else if (entry.getKey().equals(SemanticAttributes.HTTP_TARGET)) { - // TODO remove support for deprecated http.target attribute - httpTarget = (String) entry.getValue(); - } else if (entry.getKey().equals(SemanticAttributes.URL_FULL)) { - httpUrl = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_URL)) { - // TODO remove support for deprecated http.url attribute httpUrl = (String) entry.getValue(); - } else if (entry.getKey().equals(SemanticAttributes.HTTP_REQUEST_METHOD)) { - httpMethod = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_METHOD)) { - // TODO remove support for deprecated http.method attribute httpMethod = (String) entry.getValue(); - } else if (entry.getKey().equals(SemanticAttributes.SERVER_ADDRESS)) { - host = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.NET_HOST_NAME)) { - // TODO remove support for deprecated net.host.name attribute host = (String) entry.getValue(); } else if (entry.getKey().equals(SemanticAttributes.HTTP_HOST)) { // TODO (trask) remove support for deprecated http.host attribute diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java index 256be20ac..b1df48daa 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java @@ -15,25 +15,25 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_SPAN_KIND; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; -import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; -import static io.opentelemetry.semconv.SemanticAttributes.DB_OPERATION; -import static io.opentelemetry.semconv.SemanticAttributes.DB_SYSTEM; -import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_NAME; -import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_PROVIDER; -import static io.opentelemetry.semconv.SemanticAttributes.FAAS_TRIGGER; -import static io.opentelemetry.semconv.SemanticAttributes.GRAPHQL_OPERATION_TYPE; -import static io.opentelemetry.semconv.SemanticAttributes.HTTP_REQUEST_METHOD; -import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_OPERATION; -import static io.opentelemetry.semconv.SemanticAttributes.MESSAGING_SYSTEM; -import static io.opentelemetry.semconv.SemanticAttributes.PEER_SERVICE; -import static io.opentelemetry.semconv.SemanticAttributes.RPC_METHOD; -import static io.opentelemetry.semconv.SemanticAttributes.RPC_SERVICE; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_ADDRESS; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_PORT; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_ADDRESS; -import static io.opentelemetry.semconv.SemanticAttributes.SERVER_SOCKET_PORT; -import static io.opentelemetry.semconv.SemanticAttributes.URL_FULL; -import static io.opentelemetry.semconv.SemanticAttributes.URL_PATH; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SYSTEM; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_INVOKED_PROVIDER; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_TRIGGER; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.GRAPHQL_OPERATION_TYPE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_METHOD; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_TARGET; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.MESSAGING_SYSTEM; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_ADDR; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_SOCK_PEER_PORT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.PEER_SERVICE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_METHOD; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.RPC_SERVICE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -170,7 +170,7 @@ public void testServerSpanWithNullSpanName() { public void testServerSpanWithSpanNameAsHttpMethod() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("GET"); - mockAttribute(HTTP_REQUEST_METHOD, "GET"); + mockAttribute(HTTP_METHOD, "GET"); Attributes expectedAttributes = Attributes.of( @@ -178,15 +178,15 @@ public void testServerSpanWithSpanNameAsHttpMethod() { AWS_LOCAL_SERVICE, SERVICE_NAME_VALUE, AWS_LOCAL_OPERATION, UNKNOWN_OPERATION); validateAttributesProducedForSpanOfKind(expectedAttributes, SpanKind.SERVER); - mockAttribute(HTTP_REQUEST_METHOD, null); + mockAttribute(HTTP_METHOD, null); } @Test public void testServerSpanWithSpanNameWithHttpTarget() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("POST"); - mockAttribute(HTTP_REQUEST_METHOD, "POST"); - mockAttribute(URL_PATH, "/payment/123"); + mockAttribute(HTTP_METHOD, "POST"); + mockAttribute(HTTP_TARGET, "/payment/123"); Attributes expectedAttributes = Attributes.of( @@ -197,8 +197,8 @@ public void testServerSpanWithSpanNameWithHttpTarget() { AWS_LOCAL_OPERATION, "POST /payment"); validateAttributesProducedForSpanOfKind(expectedAttributes, SpanKind.SERVER); - mockAttribute(HTTP_REQUEST_METHOD, null); - mockAttribute(URL_PATH, null); + mockAttribute(HTTP_METHOD, null); + mockAttribute(HTTP_TARGET, null); } @Test @@ -283,44 +283,44 @@ public void testRemoteAttributesCombinations() { mockAttribute(GRAPHQL_OPERATION_TYPE, null); // Validate behaviour of extracting Remote Service from net.peer.name - mockAttribute(SERVER_ADDRESS, "www.example.com"); + mockAttribute(NET_PEER_NAME, "www.example.com"); validateExpectedRemoteAttributes("www.example.com", UNKNOWN_REMOTE_OPERATION); - mockAttribute(SERVER_ADDRESS, null); + mockAttribute(NET_PEER_NAME, null); // Validate behaviour of extracting Remote Service from net.peer.name and net.peer.port - mockAttribute(SERVER_ADDRESS, "192.168.0.0"); - mockAttribute(SERVER_PORT, 8081L); + mockAttribute(NET_PEER_NAME, "192.168.0.0"); + mockAttribute(NET_PEER_PORT, 8081L); validateExpectedRemoteAttributes("192.168.0.0:8081", UNKNOWN_REMOTE_OPERATION); - mockAttribute(SERVER_ADDRESS, null); - mockAttribute(SERVER_PORT, null); + mockAttribute(NET_PEER_NAME, null); + mockAttribute(NET_PEER_PORT, null); // Validate behaviour of extracting Remote Service from net.peer.socket.addr - mockAttribute(SERVER_SOCKET_ADDRESS, "www.example.com"); + mockAttribute(NET_SOCK_PEER_ADDR, "www.example.com"); validateExpectedRemoteAttributes("www.example.com", UNKNOWN_REMOTE_OPERATION); - mockAttribute(SERVER_SOCKET_ADDRESS, null); + mockAttribute(NET_SOCK_PEER_ADDR, null); // Validate behaviour of extracting Remote Service from net.peer.socket.addr and // net.sock.peer.port - mockAttribute(SERVER_SOCKET_ADDRESS, "192.168.0.0"); - mockAttribute(SERVER_SOCKET_PORT, 8081L); + mockAttribute(NET_SOCK_PEER_ADDR, "192.168.0.0"); + mockAttribute(NET_SOCK_PEER_PORT, 8081L); validateExpectedRemoteAttributes("192.168.0.0:8081", UNKNOWN_REMOTE_OPERATION); - mockAttribute(SERVER_SOCKET_ADDRESS, null); - mockAttribute(SERVER_SOCKET_PORT, null); + mockAttribute(NET_SOCK_PEER_ADDR, null); + mockAttribute(NET_SOCK_PEER_PORT, null); // Validate behavior of Remote Operation from HttpTarget - with 1st api part, then remove it - mockAttribute(URL_FULL, "http://www.example.com/payment/123"); + mockAttribute(HTTP_URL, "http://www.example.com/payment/123"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, "/payment"); - mockAttribute(URL_FULL, null); + mockAttribute(HTTP_URL, null); // Validate behavior of Remote Operation from HttpTarget - without 1st api part, then remove it - mockAttribute(URL_FULL, "http://www.example.com"); + mockAttribute(HTTP_URL, "http://www.example.com"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, "/"); - mockAttribute(URL_FULL, null); + mockAttribute(HTTP_URL, null); // Validate behavior of Remote Operation from HttpTarget - invalid url, then remove it - mockAttribute(URL_FULL, "abc"); + mockAttribute(HTTP_URL, "abc"); validateExpectedRemoteAttributes(UNKNOWN_REMOTE_SERVICE, UNKNOWN_REMOTE_OPERATION); - mockAttribute(URL_FULL, null); + mockAttribute(HTTP_URL, null); // Validate behaviour of Peer service attribute, then remove it. mockAttribute(PEER_SERVICE, "Peer service"); @@ -338,8 +338,8 @@ public void testPeerServiceDoesOverrideOtherRemoteServices() { validatePeerServiceDoesOverride(FAAS_INVOKED_PROVIDER); validatePeerServiceDoesOverride(MESSAGING_SYSTEM); validatePeerServiceDoesOverride(GRAPHQL_OPERATION_TYPE); - validatePeerServiceDoesOverride(SERVER_ADDRESS); - validatePeerServiceDoesOverride(SERVER_SOCKET_ADDRESS); + validatePeerServiceDoesOverride(NET_PEER_NAME); + validatePeerServiceDoesOverride(NET_SOCK_PEER_ADDR); // Actually testing that peer service overrides "UnknownRemoteService". validatePeerServiceDoesOverride(AttributeKey.stringKey("unknown.service.key")); } diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java index 77188a606..c2109b267 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_STATUS_CODE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -141,7 +141,7 @@ public void testOnEndMetricsGenerationWithoutSpanAttributes() { @Test public void testOnEndMetricsGenerationWithoutMetricAttributes() { - Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 500L); + Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -154,7 +154,7 @@ public void testOnEndMetricsGenerationWithoutMetricAttributes() { @Test public void testOnEndMetricsGenerationWithoutEndRequired() { - Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 500L); + Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -167,7 +167,7 @@ public void testOnEndMetricsGenerationWithoutEndRequired() { @Test public void testOnEndMetricsGenerationWithLatency() { - Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, 200L); + Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 200L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); @@ -245,7 +245,7 @@ private static ReadableSpan buildReadableSpanMock(Attributes spanAttributes) { private static ReadableSpan buildReadableSpanWithThrowableMock(Throwable throwable) { // config http status code as null - Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, null); + Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, null); ReadableSpan readableSpanMock = mock(ReadableSpan.class); SpanData mockSpanData = mock(SpanData.class); InstrumentationScopeInfo awsSdkScopeInfo = @@ -280,7 +280,7 @@ private void configureMocksForOnEnd(ReadableSpan readableSpanMock, Attributes me private void validateMetricsGeneratedForHttpStatusCode( Long httpStatusCode, ExpectedStatusMetric expectedStatusMetric) { - Attributes spanAttributes = Attributes.of(HTTP_RESPONSE_STATUS_CODE, httpStatusCode); + Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, httpStatusCode); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); configureMocksForOnEnd(readableSpanMock, metricAttributes); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java index 046b7cd11..5a51318f2 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerProviderTest.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.semconv.ResourceAttributes; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java index e783c5a10..6bb6e82a4 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplierTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.awsxray; -import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -22,8 +22,8 @@ import io.opentelemetry.sdk.testing.time.TestClock; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import io.opentelemetry.semconv.ResourceAttributes; -import io.opentelemetry.semconv.SemanticAttributes; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.io.IOException; import java.io.UncheckedIOException; import java.time.Duration; @@ -61,9 +61,9 @@ class ExactMatch { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") - .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") - .put(SemanticAttributes.URL_PATH, "/instrument-me") + .put(SemanticAttributes.HTTP_METHOD, "GET") + .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-me") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); @@ -109,8 +109,8 @@ void matches() { assertThat( applier.matches( attributes.toBuilder() - .remove(SemanticAttributes.URL_PATH) - .put(SemanticAttributes.URL_FULL, "scheme://host:port/instrument-me") + .remove(SemanticAttributes.HTTP_TARGET) + .put(SemanticAttributes.HTTP_URL, "scheme://host:port/instrument-me") .build(), resource)) .isTrue(); @@ -133,7 +133,7 @@ void serviceNameNullNotMatch() { @Test void methodNotMatch() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "POST").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "POST").build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -143,7 +143,7 @@ void hostNotMatch() { // wildcard. Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetryfio") + .put(SemanticAttributes.NET_HOST_NAME, "opentelemetryfio") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -151,18 +151,20 @@ void hostNotMatch() { @Test void pathNotMatch() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.URL_PATH, "/instrument-you").build(); + this.attributes.toBuilder() + .put(SemanticAttributes.HTTP_TARGET, "/instrument-you") + .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.URL_PATH) - .put(SemanticAttributes.URL_FULL, "scheme://host:port/instrument-you") + .remove(SemanticAttributes.HTTP_TARGET) + .put(SemanticAttributes.HTTP_URL, "scheme://host:port/instrument-you") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.URL_PATH) - .put(SemanticAttributes.URL_FULL, "scheme://host:port") + .remove(SemanticAttributes.HTTP_TARGET) + .put(SemanticAttributes.HTTP_URL, "scheme://host:port") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); @@ -170,8 +172,8 @@ void pathNotMatch() { // present. attributes = this.attributes.toBuilder() - .remove(SemanticAttributes.URL_PATH) - .put(SemanticAttributes.URL_FULL, "host:port/instrument-me") + .remove(SemanticAttributes.HTTP_TARGET) + .put(SemanticAttributes.HTTP_URL, "host:port/instrument-me") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -234,9 +236,9 @@ class WildcardMatch { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") - .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") - .put(SemanticAttributes.URL_PATH, "/instrument-me?foo=bar&cat=meow") + .put(SemanticAttributes.HTTP_METHOD, "GET") + .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-me?foo=bar&cat=meow") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); @@ -308,24 +310,22 @@ void serviceNameNotMatch() { @Test void methodMatches() { Attributes attributes = - this.attributes.toBuilder() - .put(SemanticAttributes.HTTP_REQUEST_METHOD, "BADGETGOOD") - .build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "BADGETGOOD").build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "BADGET").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "BADGET").build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "GETGET").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "GETGET").build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @Test void methodNotMatch() { Attributes attributes = - this.attributes.toBuilder().put(SemanticAttributes.HTTP_REQUEST_METHOD, "POST").build(); + this.attributes.toBuilder().put(SemanticAttributes.HTTP_METHOD, "POST").build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_REQUEST_METHOD); + attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_METHOD); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -333,27 +333,27 @@ void methodNotMatch() { void hostMatches() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "alpha.opentelemetry.io") + .put(SemanticAttributes.NET_HOST_NAME, "alpha.opentelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opfdnqtelemetry.io") + .put(SemanticAttributes.NET_HOST_NAME, "opfdnqtelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentglemetry.io") + .put(SemanticAttributes.NET_HOST_NAME, "opentglemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentglemry.io") + .put(SemanticAttributes.NET_HOST_NAME, "opentglemry.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentglemrz.io") + .put(SemanticAttributes.NET_HOST_NAME, "opentglemrz.io") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @@ -362,20 +362,20 @@ void hostMatches() { void hostNotMatch() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetryfio") + .put(SemanticAttributes.NET_HOST_NAME, "opentelemetryfio") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "opentgalemetry.io") + .put(SemanticAttributes.NET_HOST_NAME, "opentgalemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.SERVER_ADDRESS, "alpha.oentelemetry.io") + .put(SemanticAttributes.NET_HOST_NAME, "alpha.oentelemetry.io") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.SERVER_ADDRESS); + attributes = removeAttribute(this.attributes, SemanticAttributes.NET_HOST_NAME); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -383,13 +383,13 @@ void hostNotMatch() { void pathMatches() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.URL_PATH, "/instrument-me?foo=bar&cat=") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-me?foo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); // Deceptive question mark, it's actually a wildcard :-) attributes = this.attributes.toBuilder() - .put(SemanticAttributes.URL_PATH, "/instrument-meafoo=bar&cat=") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-meafoo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isTrue(); } @@ -398,15 +398,15 @@ void pathMatches() { void pathNotMatch() { Attributes attributes = this.attributes.toBuilder() - .put(SemanticAttributes.URL_PATH, "/instrument-mea?foo=bar&cat=") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-mea?foo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); attributes = this.attributes.toBuilder() - .put(SemanticAttributes.URL_PATH, "foo/instrument-meafoo=bar&cat=") + .put(SemanticAttributes.HTTP_TARGET, "foo/instrument-meafoo=bar&cat=") .build(); assertThat(applier.matches(attributes, resource)).isFalse(); - attributes = removeAttribute(this.attributes, SemanticAttributes.URL_PATH); + attributes = removeAttribute(this.attributes, SemanticAttributes.HTTP_TARGET); assertThat(applier.matches(attributes, resource)).isFalse(); } @@ -507,9 +507,9 @@ class AwsLambdaTest { private final Attributes attributes = Attributes.builder() - .put(SemanticAttributes.HTTP_REQUEST_METHOD, "GET") - .put(SemanticAttributes.SERVER_ADDRESS, "opentelemetry.io") - .put(SemanticAttributes.URL_PATH, "/instrument-me") + .put(SemanticAttributes.HTTP_METHOD, "GET") + .put(SemanticAttributes.NET_HOST_NAME, "opentelemetry.io") + .put(SemanticAttributes.HTTP_TARGET, "/instrument-me") .put(AttributeKey.stringKey("animal"), "cat") .put(AttributeKey.longKey("speed"), 10) .build(); From b9a5775386ce0282ffd80f0b714dd8011f800760 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 13 Oct 2023 14:00:21 -0700 Subject: [PATCH 080/108] Fix the build (#1075) --- .../contrib/jmxmetrics/target_systems/JettyIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/JettyIntegrationTest.java b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/JettyIntegrationTest.java index 0fb04a608..761b6c842 100644 --- a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/JettyIntegrationTest.java +++ b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/JettyIntegrationTest.java @@ -29,7 +29,7 @@ class JettyIntegrationTest extends AbstractIntegrationTest { .withDockerfileFromBuilder( builder -> builder - .from("jetty") + .from("jetty:11") .run( "java", "-jar", From 5041ea585a014f058c3c3e3eed29754b69bb74de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:39:53 -0700 Subject: [PATCH 081/108] Update dependency com.fasterxml.jackson:jackson-bom to v2.15.3 (#1073) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index d4208ac41..0cb0683d7 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -8,7 +8,7 @@ val dependencyVersions = hashMapOf() rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( - "com.fasterxml.jackson:jackson-bom:2.15.2", + "com.fasterxml.jackson:jackson-bom:2.15.3", "com.google.guava:guava-bom:32.1.3-jre", "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", From c2ea6096c65a9dfe91b4e9af92f6701b43ed032d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:40:08 -0700 Subject: [PATCH 082/108] Update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v1.31.0-alpha (#1072) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Trask Stalnaker --- dependencyManagement/build.gradle.kts | 2 +- .../prometheus/clientbridge/PrometheusCollector.java | 11 +++-------- .../clientbridge/PrometheusCollectorTest.java | 8 ++++---- .../plugin/maven/ZipEntryCreator.java | 8 ++++++++ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 0cb0683d7..4532cd917 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -13,7 +13,7 @@ val DEPENDENCY_BOMS = listOf( "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.58.0", - "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.30.0-alpha", + "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", "org.testcontainers:testcontainers-bom:1.19.1" ) diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java index c5aff3bb8..3acc1096a 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java @@ -11,7 +11,6 @@ import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.export.CollectionRegistration; import io.opentelemetry.sdk.metrics.export.MetricReader; -import io.opentelemetry.sdk.metrics.internal.export.MetricProducer; import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; import java.util.ArrayList; @@ -28,10 +27,10 @@ public final class PrometheusCollector implements MetricReader { private final Collector collector; - private volatile MetricProducer metricProducer = MetricProducer.noop(); + private volatile CollectionRegistration collectionRegistration = CollectionRegistration.noop(); PrometheusCollector() { - this.collector = new CollectorImpl(() -> getMetricProducer().collectAllMetrics()); + this.collector = new CollectorImpl(() -> collectionRegistration.collectAllMetrics()); this.collector.register(); } @@ -43,13 +42,9 @@ public static PrometheusCollector create() { return new PrometheusCollector(); } - private MetricProducer getMetricProducer() { - return metricProducer; - } - @Override public void register(CollectionRegistration registration) { - this.metricProducer = MetricProducer.asMetricProducer(registration); + this.collectionRegistration = registration; } @Override diff --git a/prometheus-client-bridge/src/test/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollectorTest.java b/prometheus-client-bridge/src/test/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollectorTest.java index b1e77a321..ebc011752 100644 --- a/prometheus-client-bridge/src/test/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollectorTest.java +++ b/prometheus-client-bridge/src/test/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollectorTest.java @@ -16,11 +16,11 @@ import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.export.CollectionRegistration; import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongPointData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData; -import io.opentelemetry.sdk.metrics.internal.export.MetricProducer; import io.opentelemetry.sdk.resources.Resource; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.exporter.common.TextFormat; @@ -36,14 +36,14 @@ @ExtendWith(MockitoExtension.class) class PrometheusCollectorTest { - @Mock MetricProducer metricProducer; + @Mock CollectionRegistration collectionRegistration; PrometheusCollector prometheusCollector; @BeforeEach void setUp() { // Apply the SDK metric producer registers with prometheus. prometheusCollector = new PrometheusCollector(); - prometheusCollector.register(metricProducer); + prometheusCollector.register(collectionRegistration); } @Test @@ -60,7 +60,7 @@ void registerWithSdkMeterProvider() { @Test void registerToDefault() throws IOException { - when(metricProducer.collectAllMetrics()).thenReturn(generateTestData()); + when(collectionRegistration.collectAllMetrics()).thenReturn(generateTestData()); StringWriter stringWriter = new StringWriter(); TextFormat.write004(stringWriter, CollectorRegistry.defaultRegistry.metricFamilySamples()); assertThat(stringWriter.toString()) diff --git a/static-instrumenter/maven-plugin/src/main/java/io/opentelemetry/contrib/staticinstrumenter/plugin/maven/ZipEntryCreator.java b/static-instrumenter/maven-plugin/src/main/java/io/opentelemetry/contrib/staticinstrumenter/plugin/maven/ZipEntryCreator.java index aee90eb75..52e81104a 100644 --- a/static-instrumenter/maven-plugin/src/main/java/io/opentelemetry/contrib/staticinstrumenter/plugin/maven/ZipEntryCreator.java +++ b/static-instrumenter/maven-plugin/src/main/java/io/opentelemetry/contrib/staticinstrumenter/plugin/maven/ZipEntryCreator.java @@ -24,6 +24,14 @@ static void moveEntryUpdating( FileSystem targetFs, String targetPath, JarEntry sourceEntry, JarFile sourceJar) throws IOException { + if (targetPath.equals( + "META-INF/services/io.opentelemetry.javaagent.tooling.BeforeAgentListener")) { + // TEMPORARY hack to make things pass after a BeforeAgentListener was added in the agent + // in https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9301 + // which then causes conflict with the BeforeAgentListener in this module + return; + } + Path entry = targetFs.getPath("/", targetPath); Files.createDirectories(entry.getParent()); try (InputStream sourceInput = sourceJar.getInputStream(sourceEntry)) { From 27e17fd0e819726944d0ca254979887de0173d84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:06:47 -0700 Subject: [PATCH 083/108] Update dependency com.squareup.okhttp3:okhttp to v4.12.0 (#1078) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 4532cd917..6843410a2 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -48,7 +48,7 @@ val CORE_DEPENDENCIES = listOf( val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", - "com.squareup.okhttp3:okhttp:4.11.0", + "com.squareup.okhttp3:okhttp:4.12.0", "com.uber.nullaway:nullaway:0.10.14", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", From e46643159a573ce00f40a9064a89abeb5166fad4 Mon Sep 17 00:00:00 2001 From: Otmar Ertl Date: Wed, 18 Oct 2023 15:37:55 +0200 Subject: [PATCH 084/108] consistent sampler prototypes using 56 bits of randomness (#1063) --- consistent-sampling/build.gradle.kts | 2 +- .../ConsistentAlwaysOffSampler.java | 26 ++ .../ConsistentAlwaysOnSampler.java | 28 ++ .../ConsistentComposedAndSampler.java | 56 +++ .../ConsistentComposedOrSampler.java | 61 ++++ .../ConsistentFixedThresholdSampler.java | 49 +++ .../ConsistentParentBasedSampler.java | 51 +++ .../ConsistentRateLimitingSampler.java | 160 +++++++++ .../consistent56/ConsistentSampler.java | 319 ++++++++++++++++++ .../consistent56/ConsistentSamplingUtil.java | 147 ++++++++ .../sampler/consistent56/OtelTraceState.java | 256 ++++++++++++++ .../consistent56/RandomValueGenerator.java | 24 ++ .../consistent56/RandomValueGenerators.java | 25 ++ .../ConsistentAlwaysOffSamplerTest.java | 31 ++ .../ConsistentAlwaysOnSamplerTest.java | 35 ++ .../ConsistentFixedThresholdSamplerTest.java | 114 +++++++ .../ConsistentRateLimitingSamplerTest.java | 231 +++++++++++++ .../consistent56/ConsistentSamplerTest.java | 261 ++++++++++++++ .../ConsistentSamplingUtilTest.java | 114 +++++++ .../consistent56/OtelTraceStateTest.java | 75 ++++ .../RandomValueGeneratorsTest.java | 22 ++ 21 files changed, 2086 insertions(+), 1 deletion(-) create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedAndSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedOrSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentParentBasedSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSampler.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtil.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceState.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerator.java create mode 100644 consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerators.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSamplerTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplerTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java create mode 100644 consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index b6700f1ff..06b330c2f 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } description = "Sampler and exporter implementations for consistent sampling" -otelJava.moduleName.set("io.opentelemetry.contrib.sampler.consistent") +otelJava.moduleName.set("io.opentelemetry.contrib.sampler") dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSampler.java new file mode 100644 index 000000000..2b95c19ce --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSampler.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import javax.annotation.concurrent.Immutable; + +@Immutable +final class ConsistentAlwaysOffSampler extends ConsistentSampler { + + ConsistentAlwaysOffSampler(RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + return 0; + } + + @Override + public String getDescription() { + return "ConsistentAlwaysOffSampler"; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSampler.java new file mode 100644 index 000000000..93db59560 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSampler.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxThreshold; + +import javax.annotation.concurrent.Immutable; + +@Immutable +final class ConsistentAlwaysOnSampler extends ConsistentSampler { + + ConsistentAlwaysOnSampler(RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + return getMaxThreshold(); + } + + @Override + public String getDescription() { + return "ConsistentAlwaysOnSampler"; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedAndSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedAndSampler.java new file mode 100644 index 000000000..de22a7056 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedAndSampler.java @@ -0,0 +1,56 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.concurrent.Immutable; + +/** + * A consistent sampler composed of two consistent samplers. + * + *

This sampler samples if both samplers would sample. + */ +@Immutable +final class ConsistentComposedAndSampler extends ConsistentSampler { + + private final ConsistentSampler sampler1; + private final ConsistentSampler sampler2; + private final String description; + + ConsistentComposedAndSampler( + ConsistentSampler sampler1, + ConsistentSampler sampler2, + RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + this.sampler1 = requireNonNull(sampler1); + this.sampler2 = requireNonNull(sampler2); + this.description = + "ConsistentComposedAndSampler{" + + "sampler1=" + + sampler1.getDescription() + + ",sampler2=" + + sampler2.getDescription() + + '}'; + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + long threshold1 = sampler1.getThreshold(parentThreshold, isRoot); + long threshold2 = sampler2.getThreshold(parentThreshold, isRoot); + if (ConsistentSamplingUtil.isValidThreshold(threshold1) + && ConsistentSamplingUtil.isValidThreshold(threshold2)) { + return Math.min(threshold1, threshold2); + } else { + return ConsistentSamplingUtil.getInvalidThreshold(); + } + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedOrSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedOrSampler.java new file mode 100644 index 000000000..542cc65bc --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedOrSampler.java @@ -0,0 +1,61 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.concurrent.Immutable; + +/** + * A consistent sampler composed of two consistent samplers. + * + *

This sampler samples if any of the two samplers would sample. + */ +@Immutable +final class ConsistentComposedOrSampler extends ConsistentSampler { + + private final ConsistentSampler sampler1; + private final ConsistentSampler sampler2; + private final String description; + + ConsistentComposedOrSampler( + ConsistentSampler sampler1, + ConsistentSampler sampler2, + RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + this.sampler1 = requireNonNull(sampler1); + this.sampler2 = requireNonNull(sampler2); + this.description = + "ConsistentComposedOrSampler{" + + "sampler1=" + + sampler1.getDescription() + + ",sampler2=" + + sampler2.getDescription() + + '}'; + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + long threshold1 = sampler1.getThreshold(parentThreshold, isRoot); + long threshold2 = sampler2.getThreshold(parentThreshold, isRoot); + if (ConsistentSamplingUtil.isValidThreshold(threshold1)) { + if (ConsistentSamplingUtil.isValidThreshold(threshold2)) { + return Math.max(threshold1, threshold2); + } + return threshold1; + } else { + if (ConsistentSamplingUtil.isValidThreshold(threshold2)) { + return threshold2; + } + return ConsistentSamplingUtil.getInvalidThreshold(); + } + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSampler.java new file mode 100644 index 000000000..dd160f387 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSampler.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateSamplingProbability; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.checkThreshold; + +public class ConsistentFixedThresholdSampler extends ConsistentSampler { + + private final long threshold; + private final String description; + + protected ConsistentFixedThresholdSampler( + long threshold, RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + checkThreshold(threshold); + this.threshold = threshold; + + String thresholdString; + if (threshold == ConsistentSamplingUtil.getMaxThreshold()) { + thresholdString = "max"; + } else { + thresholdString = + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), threshold) + .toString(); + } + + this.description = + "ConsistentFixedThresholdSampler{threshold=" + + thresholdString + + ", sampling probability=" + + calculateSamplingProbability(threshold) + + "}"; + } + + @Override + public String getDescription() { + return description; + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + return threshold; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentParentBasedSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentParentBasedSampler.java new file mode 100644 index 000000000..9d40793d9 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentParentBasedSampler.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.concurrent.Immutable; + +/** + * A consistent sampler that makes the same sampling decision as the parent. For root spans the + * sampling decision is delegated to the root sampler. + */ +@Immutable +final class ConsistentParentBasedSampler extends ConsistentSampler { + + private final ConsistentSampler rootSampler; + + private final String description; + + /** + * Constructs a new consistent parent based sampler using the given root sampler and the given + * thread-safe random generator. + * + * @param rootSampler the root sampler + * @param randomValueGenerator the function to use for generating the r-value + */ + ConsistentParentBasedSampler( + ConsistentSampler rootSampler, RandomValueGenerator randomValueGenerator) { + super(randomValueGenerator); + this.rootSampler = requireNonNull(rootSampler); + this.description = + "ConsistentParentBasedSampler{rootSampler=" + rootSampler.getDescription() + '}'; + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + if (isRoot) { + return rootSampler.getThreshold(ConsistentSamplingUtil.getInvalidThreshold(), isRoot); + } else { + return parentThreshold; + } + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSampler.java new file mode 100644 index 000000000..3e741df8d --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSampler.java @@ -0,0 +1,160 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.LongSupplier; +import javax.annotation.concurrent.Immutable; + +/** + * This consistent {@link Sampler} adjusts the sampling probability dynamically to limit the rate of + * sampled spans. + * + *

This sampler uses exponential smoothing to estimate on irregular data (compare Wright, David + * J. "Forecasting data published at irregular time intervals using an extension of Holt's method." + * Management science 32.4 (1986): 499-510.) to estimate the average waiting time between spans + * which further allows to estimate the current rate of spans. In the paper, Eq. 2 defines the + * weighted average of a sequence of data + * + *

{@code ..., X(n-2), X(n-1), X(n)} + * + *

at irregular times + * + *

{@code ..., t(n-2), t(n-1), t(n)} + * + *

as + * + *

{@code E(X(n)) := A(n) * V(n)}. + * + *

{@code A(n)} and {@code V(n)} are computed recursively using Eq. 5 and Eq. 6 given by + * + *

{@code A(n) = b(n) * A(n-1) + X(n)} and {@code V(n) = V(n-1) / (b(n) + V(n-1))} + * + *

where + * + *

{@code b(n) := (1 - a)^(t(n) - t(n-1)) = exp((t(n) - t(n-1)) * ln(1 - a))}. + * + *

Introducing + * + *

{@code C(n) := 1 / V(n)} + * + *

the recursion can be rewritten as + * + *

{@code A(n) = b(n) * A(n-1) + X(n)} and {@code C(n) = b(n) * C(n-1) + 1}. + * + *

+ * + *

Since we want to estimate the average waiting time, our data is given by + * + *

{@code X(n) := t(n) - t(n-1)}. + * + *

+ * + *

The following correspondence is used for the implementation: + * + *

    + *
  • {@code effectiveWindowNanos} corresponds to {@code A(n)} + *
  • {@code effectiveWindowCount} corresponds to {@code C(n)} + *
  • {@code decayFactor} corresponds to {@code b(n)} + *
  • {@code adaptationTimeSeconds} corresponds to {@code -1 / ln(1 - a)} + *
+ */ +final class ConsistentRateLimitingSampler extends ConsistentSampler { + + private static final double NANOS_IN_SECONDS = 1e-9; + + @Immutable + private static final class State { + private final double effectiveWindowCount; + private final double effectiveWindowNanos; + private final long lastNanoTime; + + public State(double effectiveWindowCount, double effectiveWindowNanos, long lastNanoTime) { + this.effectiveWindowCount = effectiveWindowCount; + this.effectiveWindowNanos = effectiveWindowNanos; + this.lastNanoTime = lastNanoTime; + } + } + + private final String description; + private final LongSupplier nanoTimeSupplier; + private final double inverseAdaptationTimeNanos; + private final double targetSpansPerNanosecondLimit; + private final AtomicReference state; + + /** + * Constructor. + * + * @param targetSpansPerSecondLimit the desired spans per second limit + * @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for + * exponential smoothing) + * @param randomValueGenerator the function to use for generating the r-value + * @param nanoTimeSupplier a supplier for the current nano time + */ + ConsistentRateLimitingSampler( + double targetSpansPerSecondLimit, + double adaptationTimeSeconds, + RandomValueGenerator randomValueGenerator, + LongSupplier nanoTimeSupplier) { + super(randomValueGenerator); + + if (targetSpansPerSecondLimit < 0.0) { + throw new IllegalArgumentException("Limit for sampled spans per second must be nonnegative!"); + } + if (adaptationTimeSeconds < 0.0) { + throw new IllegalArgumentException("Adaptation rate must be nonnegative!"); + } + this.description = + "ConsistentRateLimitingSampler{targetSpansPerSecondLimit=" + + targetSpansPerSecondLimit + + ", adaptationTimeSeconds=" + + adaptationTimeSeconds + + "}"; + this.nanoTimeSupplier = requireNonNull(nanoTimeSupplier); + + this.inverseAdaptationTimeNanos = NANOS_IN_SECONDS / adaptationTimeSeconds; + this.targetSpansPerNanosecondLimit = NANOS_IN_SECONDS * targetSpansPerSecondLimit; + + this.state = new AtomicReference<>(new State(0, 0, nanoTimeSupplier.getAsLong())); + } + + private State updateState(State oldState, long currentNanoTime) { + if (currentNanoTime <= oldState.lastNanoTime) { + return new State( + oldState.effectiveWindowCount + 1, oldState.effectiveWindowNanos, oldState.lastNanoTime); + } + long nanoTimeDelta = currentNanoTime - oldState.lastNanoTime; + double decayFactor = Math.exp(-nanoTimeDelta * inverseAdaptationTimeNanos); + double currentEffectiveWindowCount = oldState.effectiveWindowCount * decayFactor + 1; + double currentEffectiveWindowNanos = + oldState.effectiveWindowNanos * decayFactor + nanoTimeDelta; + return new State(currentEffectiveWindowCount, currentEffectiveWindowNanos, currentNanoTime); + } + + @Override + protected long getThreshold(long parentThreshold, boolean isRoot) { + long currentNanoTime = nanoTimeSupplier.getAsLong(); + State currentState = state.updateAndGet(s -> updateState(s, currentNanoTime)); + + double samplingProbability = + (currentState.effectiveWindowNanos * targetSpansPerNanosecondLimit) + / currentState.effectiveWindowCount; + + if (samplingProbability >= 1.) { + return ConsistentSamplingUtil.getMaxThreshold(); + } else { + return ConsistentSamplingUtil.calculateThreshold(samplingProbability); + } + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSampler.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSampler.java new file mode 100644 index 000000000..005c22d90 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSampler.java @@ -0,0 +1,319 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidRandomValue; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.isValidThreshold; +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingDecision; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.List; +import java.util.function.LongSupplier; + +/** Abstract base class for consistent samplers. */ +public abstract class ConsistentSampler implements Sampler { + + /** + * Returns a {@link ConsistentSampler} that samples all spans. + * + * @return a sampler + */ + public static ConsistentSampler alwaysOn() { + return alwaysOn(RandomValueGenerators.getDefault()); + } + + /** + * Returns a {@link ConsistentSampler} that samples all spans. + * + * @param randomValueGenerator the function to use for generating the random value + * @return a sampler + */ + public static ConsistentSampler alwaysOn(RandomValueGenerator randomValueGenerator) { + return new ConsistentAlwaysOnSampler(randomValueGenerator); + } + + /** + * Returns a {@link ConsistentSampler} that does not sample any span. + * + * @return a sampler + */ + public static ConsistentSampler alwaysOff() { + return alwaysOff(RandomValueGenerators.getDefault()); + } + + /** + * Returns a {@link ConsistentSampler} that does not sample any span. + * + * @param randomValueGenerator the function to use for generating the random value + * @return a sampler + */ + public static ConsistentSampler alwaysOff(RandomValueGenerator randomValueGenerator) { + return new ConsistentAlwaysOffSampler(randomValueGenerator); + } + + /** + * Returns a {@link ConsistentSampler} that samples each span with a fixed probability. + * + * @param samplingProbability the sampling probability + * @return a sampler + */ + public static ConsistentSampler probabilityBased(double samplingProbability) { + return probabilityBased(samplingProbability, RandomValueGenerators.getDefault()); + } + + /** + * Returns a {@link ConsistentSampler} that samples each span with a fixed probability. + * + * @param samplingProbability the sampling probability + * @param randomValueGenerator the function to use for generating the r-value + * @return a sampler + */ + public static ConsistentSampler probabilityBased( + double samplingProbability, RandomValueGenerator randomValueGenerator) { + long threshold = ConsistentSamplingUtil.calculateThreshold(samplingProbability); + return new ConsistentFixedThresholdSampler(threshold, randomValueGenerator); + } + + /** + * Returns a new {@link ConsistentSampler} that respects the sampling decision of the parent span + * or falls-back to the given sampler if it is a root span. + * + * @param rootSampler the root sampler + */ + public static ConsistentSampler parentBased(ConsistentSampler rootSampler) { + return parentBased(rootSampler, RandomValueGenerators.getDefault()); + } + + /** + * Returns a new {@link ConsistentSampler} that respects the sampling decision of the parent span + * or falls-back to the given sampler if it is a root span. + * + * @param rootSampler the root sampler + * @param randomValueGenerator the function to use for generating the random value + */ + public static ConsistentSampler parentBased( + ConsistentSampler rootSampler, RandomValueGenerator randomValueGenerator) { + return new ConsistentParentBasedSampler(rootSampler, randomValueGenerator); + } + + /** + * Returns a new {@link ConsistentSampler} that attempts to adjust the sampling probability + * dynamically to meet the target span rate. + * + * @param targetSpansPerSecondLimit the desired spans per second limit + * @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for + * exponential smoothing) + */ + public static ConsistentSampler rateLimited( + double targetSpansPerSecondLimit, double adaptationTimeSeconds) { + return rateLimited( + targetSpansPerSecondLimit, adaptationTimeSeconds, RandomValueGenerators.getDefault()); + } + + /** + * Returns a new {@link ConsistentSampler} that attempts to adjust the sampling probability + * dynamically to meet the target span rate. + * + * @param targetSpansPerSecondLimit the desired spans per second limit + * @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for + * exponential smoothing) + * @param randomValueGenerator the function to use for generating the random value + */ + public static ConsistentSampler rateLimited( + double targetSpansPerSecondLimit, + double adaptationTimeSeconds, + RandomValueGenerator randomValueGenerator) { + return rateLimited( + targetSpansPerSecondLimit, adaptationTimeSeconds, randomValueGenerator, System::nanoTime); + } + + /** + * Returns a new {@link ConsistentSampler} that attempts to adjust the sampling probability + * dynamically to meet the target span rate. + * + * @param targetSpansPerSecondLimit the desired spans per second limit + * @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for + * exponential smoothing) + * @param randomValueGenerator the function to use for generating the random value + * @param nanoTimeSupplier a supplier for the current nano time + */ + static ConsistentSampler rateLimited( + double targetSpansPerSecondLimit, + double adaptationTimeSeconds, + RandomValueGenerator randomValueGenerator, + LongSupplier nanoTimeSupplier) { + return new ConsistentRateLimitingSampler( + targetSpansPerSecondLimit, adaptationTimeSeconds, randomValueGenerator, nanoTimeSupplier); + } + + /** + * Returns a {@link ConsistentSampler} that samples a span if both this and the other given + * consistent sampler would sample the span. + * + *

If the other consistent sampler is the same as this, this consistent sampler will be + * returned. + * + *

The returned sampler takes care of setting the trace state correctly, which would not happen + * if the {@link #shouldSample(Context, String, String, SpanKind, Attributes, List)} method was + * called for each sampler individually. Also, the combined sampler is more efficient than + * evaluating the two samplers individually and combining both results afterwards. + * + * @param otherConsistentSampler the other consistent sampler + * @return the composed consistent sampler + */ + public ConsistentSampler and(ConsistentSampler otherConsistentSampler) { + if (otherConsistentSampler == this) { + return this; + } + return new ConsistentComposedAndSampler( + this, otherConsistentSampler, RandomValueGenerators.getDefault()); + } + + /** + * Returns a {@link ConsistentSampler} that samples a span if this or the other given consistent + * sampler would sample the span. + * + *

If the other consistent sampler is the same as this, this consistent sampler will be + * returned. + * + *

The returned sampler takes care of setting the trace state correctly, which would not happen + * if the {@link #shouldSample(Context, String, String, SpanKind, Attributes, List)} method was + * called for each sampler individually. Also, the combined sampler is more efficient than + * evaluating the two samplers individually and combining both results afterwards. + * + * @param otherConsistentSampler the other consistent sampler + * @return the composed consistent sampler + */ + public ConsistentSampler or(ConsistentSampler otherConsistentSampler) { + if (otherConsistentSampler == this) { + return this; + } + return new ConsistentComposedOrSampler( + this, otherConsistentSampler, RandomValueGenerators.getDefault()); + } + + private final RandomValueGenerator randomValueGenerator; + + protected ConsistentSampler(RandomValueGenerator randomValueGenerator) { + this.randomValueGenerator = requireNonNull(randomValueGenerator); + } + + @Override + public final SamplingResult shouldSample( + Context parentContext, + String traceId, + String name, + SpanKind spanKind, + Attributes attributes, + List parentLinks) { + + Span parentSpan = Span.fromContext(parentContext); + SpanContext parentSpanContext = parentSpan.getSpanContext(); + boolean isRoot = !parentSpanContext.isValid(); + boolean isParentSampled = parentSpanContext.isSampled(); + + boolean isRandomTraceIdFlagSet = false; // TODO in future get the random trace ID flag, compare + // https://www.w3.org/TR/trace-context-2/#random-trace-id-flag + + TraceState parentTraceState = parentSpanContext.getTraceState(); + String otelTraceStateString = parentTraceState.get(OtelTraceState.TRACE_STATE_KEY); + OtelTraceState otelTraceState = OtelTraceState.parse(otelTraceStateString); + + long randomValue; + if (otelTraceState.hasValidRandomValue()) { + randomValue = otelTraceState.getRandomValue(); + } else if (isRandomTraceIdFlagSet) { + randomValue = OtelTraceState.parseHex(traceId, 18, 14, getInvalidRandomValue()); + } else { + randomValue = randomValueGenerator.generate(traceId); + otelTraceState.invalidateThreshold(); + otelTraceState.setRandomValue(randomValue); + } + + long parentThreshold; + if (otelTraceState.hasValidThreshold()) { + long threshold = otelTraceState.getThreshold(); + if (((randomValue < threshold) == isParentSampled) || threshold == 0) { + parentThreshold = threshold; + } else { + parentThreshold = getInvalidThreshold(); + } + } else if (isParentSampled) { + parentThreshold = getMaxThreshold(); + } else { + parentThreshold = 0; + } + + // determine new threshold that is used for the sampling decision + long threshold = getThreshold(parentThreshold, isRoot); + + // determine sampling decision + boolean isSampled; + if (isValidThreshold(threshold)) { + isSampled = (randomValue < threshold); + if (0 < threshold && threshold < getMaxThreshold()) { + otelTraceState.setThreshold(threshold); + } else { + otelTraceState.invalidateThreshold(); + } + } else { + isSampled = isParentSampled; + otelTraceState.invalidateThreshold(); + } + + SamplingDecision samplingDecision = + isSampled ? SamplingDecision.RECORD_AND_SAMPLE : SamplingDecision.DROP; + + String newOtTraceState = otelTraceState.serialize(); + + return new SamplingResult() { + + @Override + public SamplingDecision getDecision() { + return samplingDecision; + } + + @Override + public Attributes getAttributes() { + return Attributes.empty(); + } + + @Override + public TraceState getUpdatedTraceState(TraceState parentTraceState) { + return parentTraceState.toBuilder() + .put(OtelTraceState.TRACE_STATE_KEY, newOtTraceState) + .build(); + } + }; + } + + /** + * Returns the threshold that is used for the sampling decision. + * + *

NOTE: In future, further information like span attributes could be also added as arguments + * such that the sampling probability could be made dependent on those extra arguments. However, + * in any case the returned threshold value must not depend directly or indirectly on the random + * value. In particular this means that the parent sampled flag must not be used for the + * calculation of the threshold as the sampled flag depends itself on the random value. + * + * @param parentThreshold is the threshold (if known) that was used for a consistent sampling + * decision by the parent + * @param isRoot is true for the root span + * @return the threshold to be used for the sampling decision + */ + protected abstract long getThreshold(long parentThreshold, boolean isRoot); +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtil.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtil.java new file mode 100644 index 000000000..80a6bffd2 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtil.java @@ -0,0 +1,147 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; + +public final class ConsistentSamplingUtil { + + private static final int RANDOM_VALUE_BITS = 56; + private static final long MAX_THRESHOLD = 1L << RANDOM_VALUE_BITS; + private static final long MAX_RANDOM_VALUE = MAX_THRESHOLD - 1; + private static final long INVALID_THRESHOLD = -1; + private static final long INVALID_RANDOM_VALUE = -1; + + private ConsistentSamplingUtil() {} + + /** + * Returns for a given threshold the corresponding sampling probability. + * + *

The returned value does not always exactly match the applied sampling probability, since + * some least significant binary digits may not be represented by double-precision floating point + * numbers. + * + * @param threshold the threshold + * @return the sampling probability + */ + public static double calculateSamplingProbability(long threshold) { + checkThreshold(threshold); + return threshold * 0x1p-56; + } + + /** + * Returns the closest sampling threshold that can be used to realize sampling with the given + * probability. + * + * @param samplingProbability the sampling probability + * @return the threshold + */ + public static long calculateThreshold(double samplingProbability) { + checkProbability(samplingProbability); + return Math.round(samplingProbability * 0x1p56); + } + + /** + * Calculates the adjusted count from a given threshold. + * + *

Returns 1, if the threshold is invalid. + * + *

Returns 0, if the threshold is 0. A span with zero threshold is only sampled due to a + * non-probabilistic sampling decision and therefore does not contribute to the adjusted count. + * + * @param threshold the threshold + * @return the adjusted count + */ + public static double calculateAdjustedCount(long threshold) { + if (isValidThreshold(threshold)) { + if (threshold > 0) { + return 0x1p56 / threshold; + } else { + return 0; + } + } else { + return 1.; + } + } + + /** + * Returns an invalid random value. + * + *

{@code isValidRandomValue(getInvalidRandomValue())} will always return true. + * + * @return an invalid random value + */ + public static long getInvalidRandomValue() { + return INVALID_RANDOM_VALUE; + } + + /** + * Returns an invalid threshold. + * + *

{@code isValidThreshold(getInvalidThreshold())} will always return true. + * + * @return an invalid threshold value + */ + public static long getInvalidThreshold() { + return INVALID_THRESHOLD; + } + + public static long getMaxRandomValue() { + return MAX_RANDOM_VALUE; + } + + public static long getMaxThreshold() { + return MAX_THRESHOLD; + } + + public static boolean isValidRandomValue(long randomValue) { + return 0 <= randomValue && randomValue <= getMaxRandomValue(); + } + + public static boolean isValidThreshold(long threshold) { + return 0 <= threshold && threshold <= getMaxThreshold(); + } + + public static boolean isValidProbability(double probability) { + return 0 <= probability && probability <= 1; + } + + static void checkThreshold(long threshold) { + if (!isValidThreshold(threshold)) { + throw new IllegalArgumentException("The threshold must be in the range [0,2^56]!"); + } + } + + static void checkProbability(double probability) { + if (!isValidProbability(probability)) { + throw new IllegalArgumentException("The probability must be in the range [0,1]!"); + } + } + + private static final char[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + @CanIgnoreReturnValue + static StringBuilder appendLast56BitHexEncoded(StringBuilder sb, long l) { + return appendLast56BitHexEncodedHelper(sb, l, 0); + } + + @CanIgnoreReturnValue + static StringBuilder appendLast56BitHexEncodedWithoutTrailingZeros(StringBuilder sb, long l) { + int numTrailingBits = Long.numberOfTrailingZeros(l | 0x80000000000000L); + return appendLast56BitHexEncodedHelper(sb, l, numTrailingBits); + } + + @CanIgnoreReturnValue + private static StringBuilder appendLast56BitHexEncodedHelper( + StringBuilder sb, long l, int numTrailingZeroBits) { + for (int i = 52; i >= numTrailingZeroBits - 3; i -= 4) { + sb.append(HEX_DIGITS[(int) ((l >>> i) & 0xf)]); + } + return sb; + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceState.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceState.java new file mode 100644 index 000000000..e546b184b --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceState.java @@ -0,0 +1,256 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; + +final class OtelTraceState { + + public static final String TRACE_STATE_KEY = "ot"; + + private static final String SUBKEY_RANDOM_VALUE = "rv"; + private static final String SUBKEY_THRESHOLD = "th"; + private static final int TRACE_STATE_SIZE_LIMIT = 256; + + private long randomValue; // valid in the interval [0, MAX_RANDOM_VALUE] + private long threshold; // valid in the interval [0, MAX_THRESHOLD] + + private final List otherKeyValuePairs; + + private OtelTraceState(long randomValue, long threshold, List otherKeyValuePairs) { + this.randomValue = randomValue; + this.threshold = threshold; + this.otherKeyValuePairs = otherKeyValuePairs; + } + + private OtelTraceState() { + this( + ConsistentSamplingUtil.getInvalidRandomValue(), + ConsistentSamplingUtil.getInvalidThreshold(), + Collections.emptyList()); + } + + public long getRandomValue() { + return randomValue; + } + + public long getThreshold() { + return threshold; + } + + public boolean hasValidRandomValue() { + return ConsistentSamplingUtil.isValidRandomValue(randomValue); + } + + public boolean hasValidThreshold() { + return ConsistentSamplingUtil.isValidThreshold(threshold); + } + + public void invalidateRandomValue() { + randomValue = ConsistentSamplingUtil.getInvalidRandomValue(); + } + + public void invalidateThreshold() { + threshold = ConsistentSamplingUtil.getInvalidThreshold(); + } + + /** + * Sets a new th-value. + * + *

If the given th-value is invalid, the current th-value is invalidated. + * + * @param threshold the new th-value + */ + public void setThreshold(long threshold) { + if (ConsistentSamplingUtil.isValidThreshold(threshold)) { + this.threshold = threshold; + } else { + invalidateThreshold(); + } + } + + /** + * Sets a new rv-value. + * + *

If the given rv-value is invalid, the current rv-value is invalidated. + * + * @param randomValue the new rv-value + */ + public void setRandomValue(long randomValue) { + if (ConsistentSamplingUtil.isValidRandomValue(randomValue)) { + this.randomValue = randomValue; + } else { + invalidateRandomValue(); + } + } + + /** + * Returns a string representing this state. + * + * @return a string + */ + public String serialize() { + StringBuilder sb = new StringBuilder(); + if (hasValidThreshold() && threshold < ConsistentSamplingUtil.getMaxThreshold()) { + sb.append(SUBKEY_THRESHOLD).append(':'); + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros(sb, threshold); + } + if (hasValidRandomValue()) { + if (sb.length() > 0) { + sb.append(';'); + } + sb.append(SUBKEY_RANDOM_VALUE).append(':'); + ConsistentSamplingUtil.appendLast56BitHexEncoded(sb, randomValue); + } + for (String pair : otherKeyValuePairs) { + int ex = sb.length(); + if (ex != 0) { + ex += 1; + } + if (ex + pair.length() > TRACE_STATE_SIZE_LIMIT) { + break; + } + if (sb.length() > 0) { + sb.append(';'); + } + sb.append(pair); + } + return sb.toString(); + } + + private static boolean isValueByte(char c) { + return isLowerCaseAlphaNum(c) || isUpperCaseAlpha(c) || c == '.' || c == '_' || c == '-'; + } + + private static boolean isLowerCaseAlphaNum(char c) { + return isLowerCaseAlpha(c) || isDigit(c); + } + + private static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + private static boolean isLowerCaseAlpha(char c) { + return c >= 'a' && c <= 'z'; + } + + private static boolean isUpperCaseAlpha(char c) { + return c >= 'A' && c <= 'Z'; + } + + private static long parseRandomValue(String s, int startIncl, int endIncl) { + int len = endIncl - startIncl; + if (len != 14) { + return ConsistentSamplingUtil.getInvalidRandomValue(); + } + return parseHex(s, startIncl, len, ConsistentSamplingUtil.getInvalidRandomValue()); + } + + private static long parseThreshold(String s, int startIncl, int endIncl) { + int len = endIncl - startIncl; + if (len > 14) { + return ConsistentSamplingUtil.getInvalidThreshold(); + } + return parseHex(s, startIncl, len, ConsistentSamplingUtil.getInvalidThreshold()); + } + + static long parseHex(String s, int startIncl, int len, long invalidReturnValue) { + long r = 0; + for (int i = 0; i < len; ++i) { + long c = s.charAt(startIncl + i); + long x; + if (c >= '0' && c <= '9') { + x = c - '0'; + } else if (c >= 'a' && c <= 'f') { + x = c - 'a' + 10; + } else { + return invalidReturnValue; + } + r |= x << (52 - (i << 2)); + } + return r; + } + + /** + * Parses the trace state from a given string. + * + *

If the string cannot be successfully parsed, a new empty {@code OtelTraceState2} is + * returned. + * + * @param ts the string + * @return the parsed trace state or an empty trace state in case of parsing errors + */ + public static OtelTraceState parse(@Nullable String ts) { + List otherKeyValuePairs = null; + long threshold = ConsistentSamplingUtil.getInvalidThreshold(); + long randomValue = ConsistentSamplingUtil.getInvalidRandomValue(); + + if (ts == null || ts.isEmpty()) { + return new OtelTraceState(); + } + + if (ts.length() > TRACE_STATE_SIZE_LIMIT) { + return new OtelTraceState(); + } + + int startPos = 0; + int len = ts.length(); + + while (true) { + int colonPos = startPos; + for (; colonPos < len; colonPos++) { + char c = ts.charAt(colonPos); + if (!isLowerCaseAlpha(c) && (!isDigit(c) || colonPos == startPos)) { + break; + } + } + if (colonPos == startPos || colonPos == len || ts.charAt(colonPos) != ':') { + return new OtelTraceState(); + } + + int separatorPos = colonPos + 1; + while (separatorPos < len && isValueByte(ts.charAt(separatorPos))) { + separatorPos++; + } + + if (colonPos - startPos == SUBKEY_THRESHOLD.length() + && ts.startsWith(SUBKEY_THRESHOLD, startPos)) { + threshold = parseThreshold(ts, colonPos + 1, separatorPos); + } else if (colonPos - startPos == SUBKEY_RANDOM_VALUE.length() + && ts.startsWith(SUBKEY_RANDOM_VALUE, startPos)) { + randomValue = parseRandomValue(ts, colonPos + 1, separatorPos); + } else { + if (otherKeyValuePairs == null) { + otherKeyValuePairs = new ArrayList<>(); + } + otherKeyValuePairs.add(ts.substring(startPos, separatorPos)); + } + + if (separatorPos < len && ts.charAt(separatorPos) != ';') { + return new OtelTraceState(); + } + + if (separatorPos == len) { + break; + } + + startPos = separatorPos + 1; + + // test for a trailing ; + if (startPos == len) { + return new OtelTraceState(); + } + } + + return new OtelTraceState( + randomValue, + threshold, + (otherKeyValuePairs != null) ? otherKeyValuePairs : Collections.emptyList()); + } +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerator.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerator.java new file mode 100644 index 000000000..39ba47b03 --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerator.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +/** + * A function for generating random values. + * + *

The distribution of random values generated by this function must be uniform over the range + * [0,2^56-1] + */ +@FunctionalInterface +public interface RandomValueGenerator { + + /** + * Returns a 56-bit uniformly distributed random value. + * + * @param traceId the trace ID + * @return the random value + */ + long generate(String traceId); +} diff --git a/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerators.java b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerators.java new file mode 100644 index 000000000..fcd0f6f5f --- /dev/null +++ b/consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGenerators.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxRandomValue; + +import java.util.concurrent.ThreadLocalRandom; + +final class RandomValueGenerators { + + private static final RandomValueGenerator DEFAULT = createDefault(); + + static RandomValueGenerator getDefault() { + return DEFAULT; + } + + private static RandomValueGenerator createDefault() { + return s -> ThreadLocalRandom.current().nextLong() & getMaxRandomValue(); + } + + private RandomValueGenerators() {} +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java new file mode 100644 index 000000000..60f97ac23 --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxThreshold; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class ConsistentAlwaysOffSamplerTest { + + @Test + void testDescription() { + assertThat(ConsistentSampler.alwaysOff().getDescription()) + .isEqualTo("ConsistentAlwaysOffSampler"); + } + + @Test + void testThreshold() { + assertThat(ConsistentSampler.alwaysOff().getThreshold(getInvalidThreshold(), false)).isZero(); + assertThat(ConsistentSampler.alwaysOff().getThreshold(getInvalidThreshold(), true)).isZero(); + assertThat(ConsistentSampler.alwaysOff().getThreshold(getMaxThreshold(), false)).isZero(); + assertThat(ConsistentSampler.alwaysOff().getThreshold(getMaxThreshold(), true)).isZero(); + assertThat(ConsistentSampler.alwaysOff().getThreshold(0, false)).isZero(); + assertThat(ConsistentSampler.alwaysOff().getThreshold(0, true)).isZero(); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java new file mode 100644 index 000000000..96943be5e --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxThreshold; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class ConsistentAlwaysOnSamplerTest { + + @Test + void testDescription() { + assertThat(ConsistentSampler.alwaysOn().getDescription()) + .isEqualTo("ConsistentAlwaysOnSampler"); + } + + @Test + void testThreshold() { + assertThat(ConsistentSampler.alwaysOn().getThreshold(getInvalidThreshold(), false)) + .isEqualTo(getMaxThreshold()); + assertThat(ConsistentSampler.alwaysOn().getThreshold(getInvalidThreshold(), true)) + .isEqualTo(getMaxThreshold()); + assertThat(ConsistentSampler.alwaysOn().getThreshold(getMaxThreshold(), false)) + .isEqualTo(getMaxThreshold()); + assertThat(ConsistentSampler.alwaysOn().getThreshold(getMaxThreshold(), true)) + .isEqualTo(getMaxThreshold()); + assertThat(ConsistentSampler.alwaysOn().getThreshold(0, false)).isEqualTo(getMaxThreshold()); + assertThat(ConsistentSampler.alwaysOn().getThreshold(0, true)).isEqualTo(getMaxThreshold()); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java new file mode 100644 index 000000000..340f6641f --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java @@ -0,0 +1,114 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxRandomValue; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingDecision; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.Collections; +import java.util.List; +import java.util.SplittableRandom; +import org.hipparchus.stat.inference.AlternativeHypothesis; +import org.hipparchus.stat.inference.BinomialTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ConsistentFixedThresholdSamplerTest { + + private Context parentContext; + private String traceId; + private String name; + private SpanKind spanKind; + private Attributes attributes; + private List parentLinks; + + @BeforeEach + public void init() { + + parentContext = Context.root(); + traceId = "0123456789abcdef0123456789abcdef"; + name = "name"; + spanKind = SpanKind.SERVER; + attributes = Attributes.empty(); + parentLinks = Collections.emptyList(); + } + + private void testSampling(SplittableRandom rng, double samplingProbability) { + int numSpans = 10000; + + Sampler sampler = + ConsistentSampler.probabilityBased( + samplingProbability, s -> rng.nextLong() & getMaxRandomValue()); + + int numSampled = 0; + for (long i = 0; i < numSpans; ++i) { + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (samplingResult.getDecision() == SamplingDecision.RECORD_AND_SAMPLE) { + String traceStateString = + samplingResult + .getUpdatedTraceState(TraceState.getDefault()) + .get(OtelTraceState.TRACE_STATE_KEY); + OtelTraceState traceState = OtelTraceState.parse(traceStateString); + assertThat(traceState.hasValidRandomValue()).isTrue(); + if (samplingProbability == 1.) { + assertThat(traceState.hasValidThreshold()).isFalse(); + } else { + assertThat(traceState.hasValidThreshold()).isTrue(); + assertThat(traceState.getThreshold()).isEqualTo(calculateThreshold(samplingProbability)); + } + + numSampled += 1; + } + } + + assertThat( + new BinomialTest() + .binomialTest( + numSpans, numSampled, samplingProbability, AlternativeHypothesis.TWO_SIDED)) + .isGreaterThan(0.005); + } + + @Test + public void testSampling() { + + // fix seed to get reproducible results + SplittableRandom random = new SplittableRandom(0); + + testSampling(random, 1.); + testSampling(random, 0.5); + testSampling(random, 0.25); + testSampling(random, 0.125); + testSampling(random, 0.0); + testSampling(random, 0.45); + testSampling(random, 0.2); + testSampling(random, 0.13); + testSampling(random, 0.05); + } + + @Test + public void testDescription() { + assertThat(ConsistentSampler.probabilityBased(1.0).getDescription()) + .isEqualTo("ConsistentFixedThresholdSampler{threshold=max, sampling probability=1.0}"); + assertThat(ConsistentSampler.probabilityBased(0.5).getDescription()) + .isEqualTo("ConsistentFixedThresholdSampler{threshold=8, sampling probability=0.5}"); + assertThat(ConsistentSampler.probabilityBased(0.25).getDescription()) + .isEqualTo("ConsistentFixedThresholdSampler{threshold=4, sampling probability=0.25}"); + assertThat(ConsistentSampler.probabilityBased(1e-300).getDescription()) + .isEqualTo("ConsistentFixedThresholdSampler{threshold=0, sampling probability=0.0}"); + assertThat(ConsistentSampler.probabilityBased(0).getDescription()) + .isEqualTo("ConsistentFixedThresholdSampler{threshold=0, sampling probability=0.0}"); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSamplerTest.java new file mode 100644 index 000000000..24c70e4e5 --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentRateLimitingSamplerTest.java @@ -0,0 +1,231 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxRandomValue; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.SamplingDecision; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SplittableRandom; +import java.util.concurrent.TimeUnit; +import java.util.function.LongSupplier; +import org.assertj.core.data.Percentage; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ConsistentRateLimitingSamplerTest { + + private long[] nanoTime; + private LongSupplier nanoTimeSupplier; + private Context parentContext; + private String traceId; + private String name; + private SpanKind spanKind; + private Attributes attributes; + private List parentLinks; + + private static RandomValueGenerator randomValueGenerator() { + SplittableRandom random = new SplittableRandom(0L); + return s -> random.nextLong() & getMaxRandomValue(); + } + + @BeforeEach + void init() { + nanoTime = new long[] {0L}; + nanoTimeSupplier = () -> nanoTime[0]; + parentContext = Context.root(); + traceId = "0123456789abcdef0123456789abcdef"; + name = "name"; + spanKind = SpanKind.SERVER; + attributes = Attributes.empty(); + parentLinks = Collections.emptyList(); + } + + private void advanceTime(long nanosIncrement) { + nanoTime[0] += nanosIncrement; + } + + private long getCurrentTimeNanos() { + return nanoTime[0]; + } + + @Test + void testConstantRate() { + + double targetSpansPerSecondLimit = 1000; + double adaptationTimeSeconds = 5; + + ConsistentSampler sampler = + ConsistentSampler.rateLimited( + targetSpansPerSecondLimit, + adaptationTimeSeconds, + randomValueGenerator(), + nanoTimeSupplier); + + long nanosBetweenSpans = TimeUnit.MICROSECONDS.toNanos(100); + int numSpans = 1000000; + + List spanSampledNanos = new ArrayList<>(); + + for (int i = 0; i < numSpans; ++i) { + advanceTime(nanosBetweenSpans); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision())) { + spanSampledNanos.add(getCurrentTimeNanos()); + } + } + + long numSampledSpansInLast5Seconds = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(95) && x <= TimeUnit.SECONDS.toNanos(100)) + .count(); + + assertThat(numSampledSpansInLast5Seconds / 5.) + .isCloseTo(targetSpansPerSecondLimit, Percentage.withPercentage(5)); + } + + @Test + void testRateIncrease() { + + double targetSpansPerSecondLimit = 1000; + double adaptationTimeSeconds = 5; + + ConsistentSampler sampler = + ConsistentSampler.rateLimited( + targetSpansPerSecondLimit, + adaptationTimeSeconds, + randomValueGenerator(), + nanoTimeSupplier); + + long nanosBetweenSpans1 = TimeUnit.MICROSECONDS.toNanos(100); + long nanosBetweenSpans2 = TimeUnit.MICROSECONDS.toNanos(10); + int numSpans1 = 500000; + int numSpans2 = 5000000; + + List spanSampledNanos = new ArrayList<>(); + + for (int i = 0; i < numSpans1; ++i) { + advanceTime(nanosBetweenSpans1); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision())) { + spanSampledNanos.add(getCurrentTimeNanos()); + } + } + for (int i = 0; i < numSpans2; ++i) { + advanceTime(nanosBetweenSpans2); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision())) { + spanSampledNanos.add(getCurrentTimeNanos()); + } + } + + long numSampledSpansWithin5SecondsBeforeChange = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(45) && x <= TimeUnit.SECONDS.toNanos(50)) + .count(); + long numSampledSpansWithin5SecondsAfterChange = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(50) && x <= TimeUnit.SECONDS.toNanos(55)) + .count(); + long numSampledSpansInLast5Seconds = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(95) && x <= TimeUnit.SECONDS.toNanos(100)) + .count(); + + assertThat(numSampledSpansWithin5SecondsBeforeChange / 5.) + .isCloseTo(targetSpansPerSecondLimit, Percentage.withPercentage(5)); + assertThat(numSampledSpansWithin5SecondsAfterChange / 5.) + .isGreaterThan(2. * targetSpansPerSecondLimit); + assertThat(numSampledSpansInLast5Seconds / 5.) + .isCloseTo(targetSpansPerSecondLimit, Percentage.withPercentage(5)); + } + + @Test + void testRateDecrease() { + + double targetSpansPerSecondLimit = 1000; + double adaptationTimeSeconds = 5; + + ConsistentSampler sampler = + ConsistentSampler.rateLimited( + targetSpansPerSecondLimit, + adaptationTimeSeconds, + randomValueGenerator(), + nanoTimeSupplier); + + long nanosBetweenSpans1 = TimeUnit.MICROSECONDS.toNanos(10); + long nanosBetweenSpans2 = TimeUnit.MICROSECONDS.toNanos(100); + int numSpans1 = 5000000; + int numSpans2 = 500000; + + List spanSampledNanos = new ArrayList<>(); + + for (int i = 0; i < numSpans1; ++i) { + advanceTime(nanosBetweenSpans1); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision())) { + spanSampledNanos.add(getCurrentTimeNanos()); + } + } + for (int i = 0; i < numSpans2; ++i) { + advanceTime(nanosBetweenSpans2); + SamplingResult samplingResult = + sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + if (SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision())) { + spanSampledNanos.add(getCurrentTimeNanos()); + } + } + + long numSampledSpansWithin5SecondsBeforeChange = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(45) && x <= TimeUnit.SECONDS.toNanos(50)) + .count(); + long numSampledSpansWithin5SecondsAfterChange = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(50) && x <= TimeUnit.SECONDS.toNanos(55)) + .count(); + long numSampledSpansInLast5Seconds = + spanSampledNanos.stream() + .filter(x -> x > TimeUnit.SECONDS.toNanos(95) && x <= TimeUnit.SECONDS.toNanos(100)) + .count(); + + assertThat(numSampledSpansWithin5SecondsBeforeChange / 5.) + .isCloseTo(targetSpansPerSecondLimit, Percentage.withPercentage(5)); + assertThat(numSampledSpansWithin5SecondsAfterChange / 5.) + .isLessThan(0.5 * targetSpansPerSecondLimit); + assertThat(numSampledSpansInLast5Seconds / 5.) + .isCloseTo(targetSpansPerSecondLimit, Percentage.withPercentage(5)); + } + + @Test + void testDescription() { + + double targetSpansPerSecondLimit = 123.456; + double adaptationTimeSeconds = 7.89; + ConsistentSampler sampler = + ConsistentSampler.rateLimited(targetSpansPerSecondLimit, adaptationTimeSeconds); + + assertThat(sampler.getDescription()) + .isEqualTo( + "ConsistentRateLimitingSampler{targetSpansPerSecondLimit=" + + targetSpansPerSecondLimit + + ", adaptationTimeSeconds=" + + adaptationTimeSeconds + + "}"); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplerTest.java new file mode 100644 index 000000000..e36868a56 --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplerTest.java @@ -0,0 +1,261 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxRandomValue; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.SamplingDecision; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.Collections; +import java.util.List; +import java.util.OptionalLong; +import java.util.SplittableRandom; +import org.junit.jupiter.api.Test; + +class ConsistentSamplerTest { + + private static class Input { + private static final String traceId = "00112233445566778800000000000000"; + private static final String spanId = "0123456789abcdef"; + private static final String name = "name"; + private static final SpanKind spanKind = SpanKind.SERVER; + private static final Attributes attributes = Attributes.empty(); + private static final List parentLinks = Collections.emptyList(); + private boolean parentSampled = true; + + private OptionalLong parentThreshold = OptionalLong.empty(); + private OptionalLong parentRandomValue = OptionalLong.empty(); + + private final SplittableRandom random = new SplittableRandom(0L); + + public void setParentSampled(boolean parentSampled) { + this.parentSampled = parentSampled; + } + + public void setParentThreshold(long parentThreshold) { + assertThat(parentThreshold).isBetween(0L, 0xffffffffffffffL); + this.parentThreshold = OptionalLong.of(parentThreshold); + } + + public void setParentRandomValue(long parentRandomValue) { + assertThat(parentRandomValue).isBetween(0L, 0xffffffffffffffL); + this.parentRandomValue = OptionalLong.of(parentRandomValue); + } + + public Context getParentContext() { + return createParentContext( + traceId, spanId, parentThreshold, parentRandomValue, parentSampled); + } + + public static String getTraceId() { + return traceId; + } + + public static String getName() { + return name; + } + + public static SpanKind getSpanKind() { + return spanKind; + } + + public static Attributes getAttributes() { + return attributes; + } + + public static List getParentLinks() { + return parentLinks; + } + + public RandomValueGenerator getRandomValueGenerator() { + return s -> random.nextLong() & getMaxRandomValue(); + } + } + + private static class Output { + + private final SamplingResult samplingResult; + private final Context parentContext; + + Output(SamplingResult samplingResult, Context parentContext) { + this.samplingResult = samplingResult; + this.parentContext = parentContext; + } + + boolean getSampledFlag() { + return SamplingDecision.RECORD_AND_SAMPLE.equals(samplingResult.getDecision()); + } + + OptionalLong getThreshold() { + Span parentSpan = Span.fromContext(parentContext); + OtelTraceState otelTraceState = + OtelTraceState.parse( + samplingResult + .getUpdatedTraceState(parentSpan.getSpanContext().getTraceState()) + .get(OtelTraceState.TRACE_STATE_KEY)); + return otelTraceState.hasValidThreshold() + ? OptionalLong.of(otelTraceState.getThreshold()) + : OptionalLong.empty(); + } + + OptionalLong getRandomValue() { + Span parentSpan = Span.fromContext(parentContext); + OtelTraceState otelTraceState = + OtelTraceState.parse( + samplingResult + .getUpdatedTraceState(parentSpan.getSpanContext().getTraceState()) + .get(OtelTraceState.TRACE_STATE_KEY)); + return otelTraceState.hasValidRandomValue() + ? OptionalLong.of(otelTraceState.getRandomValue()) + : OptionalLong.empty(); + } + } + + private static TraceState createTraceState(OptionalLong threshold, OptionalLong randomValue) { + OtelTraceState state = OtelTraceState.parse(""); + threshold.ifPresent(x -> state.setThreshold(x)); + randomValue.ifPresent(x -> state.setRandomValue(x)); + return TraceState.builder().put(OtelTraceState.TRACE_STATE_KEY, state.serialize()).build(); + } + + private static Context createParentContext( + String traceId, + String spanId, + OptionalLong threshold, + OptionalLong randomValue, + boolean sampled) { + TraceState parentTraceState = createTraceState(threshold, randomValue); + TraceFlags traceFlags = sampled ? TraceFlags.getSampled() : TraceFlags.getDefault(); + SpanContext parentSpanContext = + SpanContext.create(traceId, spanId, traceFlags, parentTraceState); + Span parentSpan = Span.wrap(parentSpanContext); + return parentSpan.storeInContext(Context.root()); + } + + private static Output sample(Input input, ConsistentSampler sampler) { + + Context parentContext = input.getParentContext(); + SamplingResult samplingResult = + sampler.shouldSample( + parentContext, + Input.getTraceId(), + Input.getName(), + Input.getSpanKind(), + Input.getAttributes(), + Input.getParentLinks()); + return new Output(samplingResult, parentContext); + } + + @Test + void testMaxThresholdWithoutParentRandomValue() { + + Input input = new Input(); + + ConsistentSampler sampler = ConsistentSampler.alwaysOn(input.getRandomValueGenerator()); + + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.RECORD_AND_SAMPLE); + assertThat(output.getThreshold()).isEmpty(); + assertThat(output.getRandomValue()).hasValue(0x20a8397b1dcdafL); + assertThat(output.getSampledFlag()).isTrue(); + } + + @Test + void testMaxThresholdWithParentRandomValue() { + + long parentRandomValue = 0x7f99aa40c02744L; + + Input input = new Input(); + input.setParentRandomValue(parentRandomValue); + + ConsistentSampler sampler = ConsistentSampler.alwaysOn(input.getRandomValueGenerator()); + + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.RECORD_AND_SAMPLE); + assertThat(output.getThreshold()).isEmpty(); + assertThat(output.getRandomValue()).hasValue(parentRandomValue); + assertThat(output.getSampledFlag()).isTrue(); + } + + @Test + void testMinThreshold() { + + Input input = new Input(); + + ConsistentSampler sampler = + new ConsistentFixedThresholdSampler(0L, input.getRandomValueGenerator()); + + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.DROP); + assertThat(output.getThreshold()).isEmpty(); + assertThat(output.getRandomValue()).hasValue(0x20a8397b1dcdafL); + assertThat(output.getSampledFlag()).isFalse(); + } + + @Test + void testHalfThresholdNotSampled() { + + Input input = new Input(); + input.setParentRandomValue(0x8000000000000L); + + ConsistentSampler sampler = + new ConsistentFixedThresholdSampler(0x8000000000000L, input.getRandomValueGenerator()); + + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.DROP); + assertThat(output.getThreshold()).hasValue(0x8000000000000L); + assertThat(output.getRandomValue()).hasValue(0x8000000000000L); + assertThat(output.getSampledFlag()).isFalse(); + } + + @Test + void testHalfThresholdSampled() { + + Input input = new Input(); + input.setParentRandomValue(0x7ffffffffffffL); + + ConsistentSampler sampler = + new ConsistentFixedThresholdSampler(0x8000000000000L, input.getRandomValueGenerator()); + + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.RECORD_AND_SAMPLE); + assertThat(output.getThreshold()).hasValue(0x8000000000000L); + assertThat(output.getRandomValue()).hasValue(0x7ffffffffffffL); + assertThat(output.getSampledFlag()).isTrue(); + } + + @Test + void testParentExtraordinarySampledButChildNotSampled() { + + Input input = new Input(); + input.setParentThreshold(0L); + input.setParentSampled(true); + + ConsistentSampler sampler = + new ConsistentFixedThresholdSampler(0x0L, input.getRandomValueGenerator()); + Output output = sample(input, sampler); + + assertThat(output.samplingResult.getDecision()).isEqualTo(SamplingDecision.DROP); + + assertThat(output.getThreshold()).isEmpty(); + assertThat(output.getRandomValue()).isNotEmpty(); + assertThat(output.getSampledFlag()).isFalse(); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java new file mode 100644 index 000000000..944ace75b --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java @@ -0,0 +1,114 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateAdjustedCount; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateSamplingProbability; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidRandomValue; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.isValidRandomValue; +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.isValidThreshold; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +import org.junit.jupiter.api.Test; + +public class ConsistentSamplingUtilTest { + + @Test + void testCalculateSamplingProbability() { + assertThat(calculateSamplingProbability(0L)).isEqualTo(0.); + assertThat(calculateSamplingProbability(0x40000000000000L)).isEqualTo(0.25); + assertThat(calculateSamplingProbability(0x80000000000000L)).isEqualTo(0.5); + assertThat(calculateSamplingProbability(0x100000000000000L)).isEqualTo(1.); + assertThatIllegalArgumentException().isThrownBy(() -> calculateSamplingProbability(-1)); + assertThatIllegalArgumentException() + .isThrownBy(() -> calculateSamplingProbability(0x100000000000001L)); + } + + @Test + void testCalculateThreshold() { + assertThat(calculateThreshold(0.)).isEqualTo(0L); + assertThat(calculateThreshold(0.25)).isEqualTo(0x40000000000000L); + assertThat(calculateThreshold(0.5)).isEqualTo(0x80000000000000L); + assertThat(calculateThreshold(1.)).isEqualTo(0x100000000000000L); + assertThatIllegalArgumentException().isThrownBy(() -> calculateThreshold(Math.nextDown(0.))); + assertThatIllegalArgumentException().isThrownBy(() -> calculateThreshold(Math.nextUp(1.))); + assertThatIllegalArgumentException() + .isThrownBy(() -> calculateThreshold(Double.POSITIVE_INFINITY)); + assertThatIllegalArgumentException() + .isThrownBy(() -> calculateThreshold(Double.NEGATIVE_INFINITY)); + assertThatIllegalArgumentException().isThrownBy(() -> calculateThreshold(Double.NaN)); + } + + @Test + void testGetInvalidRandomValue() { + assertThat(isValidRandomValue(getInvalidRandomValue())).isFalse(); + } + + @Test + void testGetInvalidThreshold() { + assertThat(isValidThreshold(getInvalidThreshold())).isFalse(); + } + + @Test + void testGetMaxThreshold() { + assertThat(ConsistentSamplingUtil.getMaxThreshold()).isEqualTo(0x100000000000000L); + } + + @Test + void testGetMaxRandomValue() { + assertThat(ConsistentSamplingUtil.getMaxRandomValue()).isEqualTo(0xFFFFFFFFFFFFFFL); + } + + @Test + void testCalculateAdjustedCount() { + assertThat(calculateAdjustedCount(0L)).isZero(); + assertThat(calculateAdjustedCount(0x40000000000000L)).isEqualTo(4.); + assertThat(calculateAdjustedCount(0x80000000000000L)).isEqualTo(2.); + assertThat(calculateAdjustedCount(0x100000000000000L)).isOne(); + assertThat(calculateAdjustedCount(-1)).isOne(); + assertThat(calculateAdjustedCount(0x100000000000001L)).isOne(); + } + + @Test + void testAppendLast56BitHexEncoded() { + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncoded(new StringBuilder(), 0x3a436f7842456L)) + .hasToString("03a436f7842456"); + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncoded( + new StringBuilder(), 0x3a436f7842456abL)) + .hasToString("a436f7842456ab"); + assertThat(ConsistentSamplingUtil.appendLast56BitHexEncoded(new StringBuilder(), 0L)) + .hasToString("00000000000000"); + } + + @Test + void testAppendLast56BitHexEncodedWithoutTrailingZeros() { + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), 0x3a436f7842456L)) + .hasToString("03a436f7842456"); + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), 0x3a436f7842456abL)) + .hasToString("a436f7842456ab"); + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), 0x80000000000000L)) + .hasToString("8"); + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), 0x11000000000000L)) + .hasToString("11"); + assertThat( + ConsistentSamplingUtil.appendLast56BitHexEncodedWithoutTrailingZeros( + new StringBuilder(), 0L)) + .hasToString("0"); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java new file mode 100644 index 000000000..a131e9b78 --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java @@ -0,0 +1,75 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; + +public class OtelTraceStateTest { + + private static String getXString(int len) { + return Stream.generate(() -> "X").limit(len).collect(Collectors.joining()); + } + + @Test + public void test() { + + assertEquals("", OtelTraceState.parse("").serialize()); + assertEquals("", OtelTraceState.parse("").serialize()); + + assertEquals("", OtelTraceState.parse("a").serialize()); + assertEquals("", OtelTraceState.parse("#").serialize()); + assertEquals("", OtelTraceState.parse(" ").serialize()); + + assertEquals("rv:1234567890abcd", OtelTraceState.parse("rv:1234567890abcd").serialize()); + assertEquals("rv:01020304050607", OtelTraceState.parse("rv:01020304050607").serialize()); + assertEquals("", OtelTraceState.parse("rv:1234567890abcde").serialize()); + + assertEquals("th:1234567890abcd", OtelTraceState.parse("th:1234567890abcd").serialize()); + assertEquals("th:01020304050607", OtelTraceState.parse("th:01020304050607").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); + assertEquals("th:12345", OtelTraceState.parse("th:1234500000000").serialize()); + assertEquals("th:0", OtelTraceState.parse("th:0").serialize()); // TODO + assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); + assertEquals("", OtelTraceState.parse("th:1234567890abcde").serialize()); + + assertEquals( + "th:1234567890abcd;rv:1234567890abcd;a:" + getXString(214) + ";x:3", + OtelTraceState.parse("a:" + getXString(214) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()); + assertEquals( + "", + OtelTraceState.parse("a:" + getXString(215) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()); + + assertEquals("", OtelTraceState.parse("th:x").serialize()); + assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:1000000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:100000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:1000000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:100000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:1000000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:100000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:1000").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:100").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:10").serialize()); + assertEquals("th:1", OtelTraceState.parse("th:1").serialize()); + + assertEquals("th:10000000000001", OtelTraceState.parse("th:10000000000001").serialize()); + assertEquals("th:1000000000001", OtelTraceState.parse("th:10000000000010").serialize()); + assertEquals("", OtelTraceState.parse("rv:x").serialize()); + assertEquals("", OtelTraceState.parse("rv:100000000000000").serialize()); + assertEquals("rv:10000000000000", OtelTraceState.parse("rv:10000000000000").serialize()); + assertEquals("", OtelTraceState.parse("rv:1000000000000").serialize()); + } +} diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java new file mode 100644 index 000000000..ab7d378b6 --- /dev/null +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sampler.consistent56; + +import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxRandomValue; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class RandomValueGeneratorsTest { + @Test + void testRandomRange() { + int attempts = 10000; + for (int i = 0; i < attempts; ++i) { + assertThat(RandomValueGenerators.getDefault().generate("")) + .isBetween(0L, getMaxRandomValue()); + } + } +} From 5c6ac6fa1165054e213ba5c90d6d75fdf0ee2857 Mon Sep 17 00:00:00 2001 From: Jean Bisutti Date: Wed, 18 Oct 2023 17:53:59 +0200 Subject: [PATCH 085/108] Rename runtime attach method (#1077) --- runtime-attach/README.md | 2 +- .../opentelemetry/contrib/attach/core/CoreRuntimeAttach.java | 2 +- .../java/io/opentelemetry/contrib/attach/RuntimeAttach.java | 4 ++-- .../attach/AgentDisabledByEnvironmentVariableTest.java | 2 +- .../contrib/attach/AgentDisabledBySystemPropertyTest.java | 2 +- .../opentelemetry/contrib/attach/RunTimeAttachBasicTest.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/runtime-attach/README.md b/runtime-attach/README.md index 695124f8e..294345a75 100644 --- a/runtime-attach/README.md +++ b/runtime-attach/README.md @@ -39,7 +39,7 @@ We give below an example for Spring Boot applications: public class SpringBootApp { public static void main(String[] args) { - RuntimeAttach.attachJavaagentToCurrentJVM(); + RuntimeAttach.attachJavaagentToCurrentJvm(); SpringApplication.run(SpringBootApp.class, args); } diff --git a/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java b/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java index dab3217fb..ee5545f7b 100644 --- a/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java +++ b/runtime-attach/runtime-attach-core/src/main/java/io/opentelemetry/contrib/attach/core/CoreRuntimeAttach.java @@ -35,7 +35,7 @@ public CoreRuntimeAttach(String agentJarResourceName) { * beginning of the main method. */ @SuppressWarnings("MemberName") - public void attachJavaagentToCurrentJVM() { + public void attachJavaagentToCurrentJvm() { if (!shouldAttach()) { return; } diff --git a/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java b/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java index 9c97720a4..2d1e1ff11 100644 --- a/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java +++ b/runtime-attach/runtime-attach/src/main/java/io/opentelemetry/contrib/attach/RuntimeAttach.java @@ -15,11 +15,11 @@ public final class RuntimeAttach { * beginning of the main method. */ @SuppressWarnings("MemberName") - public static void attachJavaagentToCurrentJVM() { + public static void attachJavaagentToCurrentJvm() { CoreRuntimeAttach distroRuntimeAttach = new CoreRuntimeAttach("/otel-agent.jar"); - distroRuntimeAttach.attachJavaagentToCurrentJVM(); + distroRuntimeAttach.attachJavaagentToCurrentJvm(); } private RuntimeAttach() {} diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java index 5ad6f71a7..41571a2e4 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java @@ -14,7 +14,7 @@ public class AgentDisabledByEnvironmentVariableTest extends AbstractAttachmentTe @Test void shouldNotAttachWhenAgentDisabledWithEnvVariable() { - RuntimeAttach.attachJavaagentToCurrentJVM(); + RuntimeAttach.attachJavaagentToCurrentJvm(); verifyNoAttachment(); } diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java index 39a071ee2..a24c81296 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java @@ -14,7 +14,7 @@ public class AgentDisabledBySystemPropertyTest extends AbstractAttachmentTest { @Test void shouldNotAttachWhenAgentDisabledWithProperty() { - RuntimeAttach.attachJavaagentToCurrentJVM(); + RuntimeAttach.attachJavaagentToCurrentJvm(); verifyNoAttachment(); } diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java index 3f0436472..5d8f201ae 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java @@ -14,7 +14,7 @@ public class RunTimeAttachBasicTest extends AbstractAttachmentTest { @Test void shouldAttach() { - RuntimeAttach.attachJavaagentToCurrentJVM(); + RuntimeAttach.attachJavaagentToCurrentJvm(); verifyAttachment(); } From 62045cce44b21528ffe884136af1ff8aff2c388e Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 18 Oct 2023 08:58:01 -0700 Subject: [PATCH 086/108] Update change log (#1076) --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6438e06..d8612f203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ ## Unreleased +### Consistent sampling + +- Explicitly pass invalid p-value to root sampler + ([#1053](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1053)) +- Consistent sampler prototypes using 56 bits of randomness + ([#1063](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1063)) + +### Runtime attach + +- Rename runtime attach method from `attachJavaagentToCurrentJVM` + to `attachJavaagentToCurrentJvm` + ([#1077](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1077)) + +### Samplers + +- Support `thread.name` attributes in RuleBasedRoutingSampler + ([#1030](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/1030)) + ## Version 1.30.0 (2023-09-18) ### Disk buffering From 91789860f67824980e212e10945d75c29cb25ae6 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:30:50 +0200 Subject: [PATCH 087/108] Update version to 1.32.0-SNAPSHOT (#1079) --- CHANGELOG.md | 2 ++ version.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8612f203..67128b5a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## Version 1.31.0 (2023-10-18) + ### Consistent sampling - Explicitly pass invalid p-value to root sampler diff --git a/version.gradle.kts b/version.gradle.kts index a7e1145a2..043387ffc 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.31.0-SNAPSHOT" -val alphaVersion = "1.31.0-alpha-SNAPSHOT" +val stableVersion = "1.32.0-SNAPSHOT" +val alphaVersion = "1.32.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") { From aeaa483561c973d43265d8d2afc99bc589637dc3 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 18 Oct 2023 11:37:39 -0700 Subject: [PATCH 088/108] Fix broken links (#1082) --- maven-extension/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/maven-extension/README.md b/maven-extension/README.md index 292c38b3b..3ae23c7f9 100644 --- a/maven-extension/README.md +++ b/maven-extension/README.md @@ -192,9 +192,8 @@ Otherwise, the instrumentation of the Maven plugin is noop. It is recommended to enrich spans using the [OpenTelemetry Semantic Conventions](https://opentelemetry.io/docs/concepts/semantic-conventions/) to improve the visualization and analysis in Observability products. -The [HTTP](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/) -and [database client calls](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/database/) -conventions are particularly useful when invoking external systems. +The HTTP and database client [semantic conventions](https://github.com/open-telemetry/semantic-conventions) +are particularly useful when invoking external systems. Steps to instrument a Maven Mojo: From 928b5a4756727593cfcb14e66478022f1b3af811 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:03:08 -0700 Subject: [PATCH 089/108] Update dependency com.uber.nullaway:nullaway to v0.10.15 (#1084) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 6843410a2..cc51bac7d 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -49,7 +49,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.12.0", - "com.uber.nullaway:nullaway:0.10.14", + "com.uber.nullaway:nullaway:0.10.15", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From 066a16eebf1f90388f34ef2ceee5e32655b1acbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 15:38:50 -0700 Subject: [PATCH 090/108] Update dependency io.grpc:grpc-bom to v1.59.0 (#1085) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index cc51bac7d..d6697b9d1 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -12,7 +12,7 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:32.1.3-jre", "com.linecorp.armeria:armeria-bom:1.25.2", "org.junit:junit-bom:5.10.0", - "io.grpc:grpc-bom:1.58.0", + "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", "org.testcontainers:testcontainers-bom:1.19.1" ) From c0b35d751de923d1792c90886f1d01f5d6b076cc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 18:23:17 -0700 Subject: [PATCH 091/108] Update dependency org.apache.maven.plugin-tools:maven-plugin-annotations to v3.10.1 (#1086) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- static-instrumenter/maven-plugin/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static-instrumenter/maven-plugin/build.gradle.kts b/static-instrumenter/maven-plugin/build.gradle.kts index 8777917ec..8d684290b 100644 --- a/static-instrumenter/maven-plugin/build.gradle.kts +++ b/static-instrumenter/maven-plugin/build.gradle.kts @@ -17,11 +17,11 @@ otelJava { dependencies { implementation("org.apache.maven:maven-plugin-api:3.5.0") // do not auto-update this version implementation("org.apache.maven:maven-project:2.2.1") - compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations:3.9.0") + compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.1") compileOnly("org.apache.maven:maven-core:3.5.0") // do not auto-update this version compileOnly("org.slf4j:slf4j-api") - testImplementation("org.apache.maven.plugin-tools:maven-plugin-annotations:3.9.0") + testImplementation("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.1") testImplementation("org.apache.maven:maven-core:3.5.0") testImplementation("org.slf4j:slf4j-simple") } From a18177050f2d9338226a99fd01edbd03e7aa0f6f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 06:44:05 -0700 Subject: [PATCH 092/108] Update dependency com.linecorp.armeria:armeria-bom to v1.26.0 (#1088) --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index d6697b9d1..fb4d5c4ca 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.3", "com.google.guava:guava-bom:32.1.3-jre", - "com.linecorp.armeria:armeria-bom:1.25.2", + "com.linecorp.armeria:armeria-bom:1.26.0", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", From ae0c8c2871f2c9b12d9ab10db07df8281fac9ecf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 12:23:11 -0700 Subject: [PATCH 093/108] Update plugin me.champeau.jmh to v0.7.2 (#1089) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 86f13f37a..ba9ed7039 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -3,7 +3,7 @@ import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer plugins { id("otel.java-conventions") id("otel.publish-conventions") - id("me.champeau.jmh") version "0.7.1" + id("me.champeau.jmh") version "0.7.2" id("ru.vyarus.animalsniffer") version "1.7.1" id("com.squareup.wire") version "4.9.1" } From dc3b6e78a81899e78670f5d0e97e2c5a9796dacd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:48:33 -0700 Subject: [PATCH 094/108] Update dependency com.uber.nullaway:nullaway to v0.10.16 (#1091) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index fb4d5c4ca..4bc5963a1 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -49,7 +49,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.12.0", - "com.uber.nullaway:nullaway:0.10.15", + "com.uber.nullaway:nullaway:0.10.16", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From c31ccd40dc859e87f2a154c009721485b22604e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:05:24 -0800 Subject: [PATCH 095/108] Update dependency com.linecorp.armeria:armeria-bom to v1.26.2 (#1090) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 4bc5963a1..8ab86865d 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.3", "com.google.guava:guava-bom:32.1.3-jre", - "com.linecorp.armeria:armeria-bom:1.26.0", + "com.linecorp.armeria:armeria-bom:1.26.2", "org.junit:junit-bom:5.10.0", "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", From 1459cf3bed8cd41514c0b362a56c7d5bc364cdb4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:07:49 -0800 Subject: [PATCH 096/108] Update dependency com.toasttab.android:gummy-bears-api-24 to v0.6.1 (#1092) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index ba9ed7039..c434dbad5 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { api("io.opentelemetry:opentelemetry-sdk") compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") - signature("com.toasttab.android:gummy-bears-api-24:0.5.1@signature") + signature("com.toasttab.android:gummy-bears-api-24:0.6.1@signature") testImplementation("org.mockito:mockito-inline") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") } From 1b7d0c638f56b75965f036c56947c3b9b7c9f10a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:08:55 -0800 Subject: [PATCH 097/108] Update dependency org.apache.maven.plugin-tools:maven-plugin-annotations to v3.10.2 (#1095) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- static-instrumenter/maven-plugin/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static-instrumenter/maven-plugin/build.gradle.kts b/static-instrumenter/maven-plugin/build.gradle.kts index 8d684290b..48c7004bd 100644 --- a/static-instrumenter/maven-plugin/build.gradle.kts +++ b/static-instrumenter/maven-plugin/build.gradle.kts @@ -17,11 +17,11 @@ otelJava { dependencies { implementation("org.apache.maven:maven-plugin-api:3.5.0") // do not auto-update this version implementation("org.apache.maven:maven-project:2.2.1") - compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.1") + compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.2") compileOnly("org.apache.maven:maven-core:3.5.0") // do not auto-update this version compileOnly("org.slf4j:slf4j-api") - testImplementation("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.1") + testImplementation("org.apache.maven.plugin-tools:maven-plugin-annotations:3.10.2") testImplementation("org.apache.maven:maven-core:3.5.0") testImplementation("org.slf4j:slf4j-simple") } From 2983ea70e9c794c4ae44827cc7dfa4cfddeb501f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 8 Nov 2023 18:09:41 +0100 Subject: [PATCH 098/108] add extended tracer module (#759) Co-authored-by: Trask Stalnaker --- .github/scripts/draft-change-log-entries.sh | 1 + extended-tracer/README.md | 168 +++++++++ extended-tracer/build.gradle.kts | 12 + .../contrib/tracer/Propagation.java | 91 +++++ .../contrib/tracer/SpanCallback.java | 18 + .../contrib/tracer/SpanRunnable.java | 17 + .../opentelemetry/contrib/tracer/Tracing.java | 319 ++++++++++++++++++ .../contrib/tracer/TracingTest.java | 200 +++++++++++ settings.gradle.kts | 1 + 9 files changed, 827 insertions(+) create mode 100644 extended-tracer/README.md create mode 100644 extended-tracer/build.gradle.kts create mode 100644 extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Propagation.java create mode 100644 extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanCallback.java create mode 100644 extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanRunnable.java create mode 100644 extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Tracing.java create mode 100644 extended-tracer/src/test/java/io/opentelemetry/contrib/tracer/TracingTest.java diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh index 55eb299b6..eff9b6e0a 100755 --- a/.github/scripts/draft-change-log-entries.sh +++ b/.github/scripts/draft-change-log-entries.sh @@ -36,6 +36,7 @@ component_names["maven-extension/"]="Maven extension" component_names["micrometer-meter-provider/"]="Micrometer MeterProvider" component_names["noop-api/"]="No-op API" component_names["processors/"]="Telemetry processors" +component_names["extended-tracer/"]="Extended Tracer" component_names["prometheus-client-bridge/"]="Prometheus client bridge" component_names["runtime-attach/"]="Runtime attach" component_names["resource-providers/"]="Resource providers" diff --git a/extended-tracer/README.md b/extended-tracer/README.md new file mode 100644 index 000000000..78f20f455 --- /dev/null +++ b/extended-tracer/README.md @@ -0,0 +1,168 @@ +# extended-tracer + +Utility methods to make it easier to use the OpenTelemetry tracer. + +## Usage Examples + +Here are some examples how the utility methods can help reduce boilerplate code. + +### Tracing a function + +Before: + +```java +Span span = tracer.spanBuilder("reset_checkout").startSpan(); +String transactionId; +try (Scope scope = span.makeCurrent()) { + transactionId = resetCheckout(cartId); +} catch (Throwable e) { + span.setStatus(StatusCode.ERROR); + span.recordException(e); + throw e; // or throw new RuntimeException(e) - depending on your error handling strategy +} finally { + span.end(); +} +``` + +After: + +```java +Tracing tracing = new Tracing(openTelemetry, "service"); +String transactionId = tracing.call("reset_checkout", () -> resetCheckout(cartId)); +``` + +Note: + +- Use `run` instead of `call` if the function returns `void`. +- Exceptions are re-thrown without modification - see [Exception handling](#exception-handling) + for more details. + +### Trace context propagation + +Before: + +```java +Map propagationHeaders = new HashMap<>(); +openTelemetry + .getPropagators() + .getTextMapPropagator() + .inject( + Context.current(), + propagationHeaders, + (map, key, value) -> { + if (map != null) { + map.put(key, value); + } + }); + +// add propagationHeaders to request headers and call checkout service +``` + +```java +// in checkout service: get request headers into a Map requestHeaders +Map requestHeaders = new HashMap<>(); +String cartId = "cartId"; + +SpanBuilder spanBuilder = tracer.spanBuilder("checkout_cart"); +String transactionId; + +TextMapGetter> TEXT_MAP_GETTER = + new TextMapGetter>() { + @Override + public Set keys(Map carrier) { + return carrier.keySet(); + } + + @Override + @Nullable + public String get(@Nullable Map carrier, String key) { + //noinspection ConstantConditions + return carrier == null ? null : carrier.get(key); + } + }; + +Map normalizedTransport = + requestHeaders.entrySet().stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toLowerCase(Locale.ROOT), Map.Entry::getValue)); +Context newContext = openTelemetry + .getPropagators() + .getTextMapPropagator() + .extract(Context.current(), normalizedTransport, TEXT_MAP_GETTER); +try (Scope ignore = newContext.makeCurrent()) { + Span span = spanBuilder.setSpanKind(SERVER).startSpan(); + try (Scope scope = span.makeCurrent()) { + transactionId = processCheckout(cartId); + } catch (Throwable e) { + span.setStatus(StatusCode.ERROR); + span.recordException(e); + throw e; // or throw new RuntimeException(e) - depending on your error handling strategy + } finally { + span.end(); + } +} +``` + +After: + +```java +Tracing tracing = new Tracing(openTelemetry, "service"); +Map propagationHeaders = tracing.getTextMapPropagationContext(); +// add propagationHeaders to request headers and call checkout service +``` + +```java +// in checkout service: get request headers into a Map requestHeaders +Map requestHeaders = new HashMap<>(); +String cartId = "cartId"; + +Tracing tracing = new Tracing(openTelemetry, "service"); +String transactionId = tracing.traceServerSpan(requestHeaders, + tracer.spanBuilder("checkout_cart"), () -> processCheckout(cartId)); +``` + +Note: + +- You can use `traceConsumerSpan` if you want to trace a consumer (e.g. from a message queue) + instead of a server. +- Exceptions are re-thrown without modification - see [Exception handling](#exception-handling) + for more details. + +### Setting baggage entries + +Before: + +```java +BaggageBuilder builder = Baggage.current().toBuilder(); +builder.put("key", "value"); +Context context = builder.build().storeInContext(Context.current()); +try (Scope ignore = context.makeCurrent()) { + String value = Baggage.current().getEntryValue("key"); +} +``` + +After: + +```java +Tracing tracing = new Tracing(openTelemetry, "service"); +String value = Tracing.callWithBaggage( + Collections.singletonMap("key", "value"), + () -> Baggage.current().getEntryValue("key")) +``` + +## Exception handling + +`Tracing` re-throws exceptions without modification. This means you can catch exceptions around +`Tracing` calls and handle them as you would without `Tracing`. + +Note that the `Tracing` methods do not declare any checked exceptions +(the idea is taken from [@SneakyThrows](https://projectlombok.org/features/SneakyThrows)). +Declaring a checked exception would force callers to handle it, which would create a lot of +boilerplate code. Instead, `Tracing` re-throws checked exceptions as unchecked exceptions. + +## Component owners + +- [Gregor Zeitlinger](https://github.com/zeitlinger), Grafana Labs + +Learn more about component owners in [component_owners.yml](../.github/component_owners.yml). diff --git a/extended-tracer/build.gradle.kts b/extended-tracer/build.gradle.kts new file mode 100644 index 000000000..af1ac258c --- /dev/null +++ b/extended-tracer/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id("otel.java-conventions") +} + +description = "Extended Tracer" +otelJava.moduleName.set("io.opentelemetry.contrib.extended-tracer") + +dependencies { + api("io.opentelemetry:opentelemetry-api") + testImplementation("io.opentelemetry:opentelemetry-sdk-testing") + testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") +} diff --git a/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Propagation.java b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Propagation.java new file mode 100644 index 000000000..66c9f84be --- /dev/null +++ b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Propagation.java @@ -0,0 +1,91 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.tracer; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.Nullable; + +/** + * Utility class to simplify context propagation. + * + *

The README + * explains the use cases in more detail. + */ +public final class Propagation { + + private Propagation() {} + + private static final TextMapGetter> TEXT_MAP_GETTER = + new TextMapGetter>() { + @Override + public Set keys(Map carrier) { + return carrier.keySet(); + } + + @Override + @Nullable + public String get(@Nullable Map carrier, String key) { + //noinspection ConstantConditions + return carrier == null ? null : carrier.get(key); + } + }; + + /** + * Injects the current context into a string map, which can then be added to HTTP headers or the + * metadata of an event. + */ + public static Map getTextMapPropagationContext(OpenTelemetry openTelemetry) { + Map carrier = new HashMap<>(); + //noinspection ConstantConditions + openTelemetry + .getPropagators() + .getTextMapPropagator() + .inject( + Context.current(), + carrier, + (map, key, value) -> { + if (map != null) { + map.put(key, value); + } + }); + + return carrier; + } + + /** + * Extract the context from a string map, which you get from HTTP headers of the metadata of an + * event you're processing. + * + * @param carrier the string map + */ + static Context extractTextMapPropagationContext( + OpenTelemetry openTelemetry, Map carrier) { + Context current = Context.current(); + //noinspection ConstantConditions + if (carrier == null) { + return current; + } + // HTTP headers are case-insensitive. As we're using Map, which is case-sensitive, we need to + // normalize all the keys + Map normalizedCarrier = + carrier.entrySet().stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toLowerCase(Locale.ROOT), Map.Entry::getValue)); + return openTelemetry + .getPropagators() + .getTextMapPropagator() + .extract(current, normalizedCarrier, TEXT_MAP_GETTER); + } +} diff --git a/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanCallback.java b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanCallback.java new file mode 100644 index 000000000..d39e9e631 --- /dev/null +++ b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanCallback.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.tracer; + +/** + * An interface for creating a lambda that is wrapped in a span, returns a value, and that may + * throw, similar to TransactionCallback. + * + * @param Thrown exception type. + */ +@FunctionalInterface +public interface SpanCallback { + T doInSpan() throws E; +} diff --git a/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanRunnable.java b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanRunnable.java new file mode 100644 index 000000000..0e440726d --- /dev/null +++ b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/SpanRunnable.java @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.tracer; + +/** + * An interface for creating a lambda that is wrapped in a span and that may throw, similar to TransactionCallback. + * + * @param Thrown exception type. + */ +@FunctionalInterface +public interface SpanRunnable { + void doInSpan() throws E; +} diff --git a/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Tracing.java b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Tracing.java new file mode 100644 index 000000000..d868900d4 --- /dev/null +++ b/extended-tracer/src/main/java/io/opentelemetry/contrib/tracer/Tracing.java @@ -0,0 +1,319 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.tracer; + +import static io.opentelemetry.api.trace.SpanKind.CONSUMER; +import static io.opentelemetry.api.trace.SpanKind.SERVER; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.baggage.BaggageBuilder; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import java.util.Map; +import java.util.function.BiConsumer; + +/** + * Utility class to simplify tracing. + * + *

The README + * explains the use cases in more detail. + */ +public final class Tracing { + + private final OpenTelemetry openTelemetry; + + private final Tracer tracer; + + /** + * Creates a new instance of {@link Tracing}. + * + * @param openTelemetry the {@link OpenTelemetry} instance + * @param instrumentationScopeName the name of the tracer to use + */ + public Tracing(OpenTelemetry openTelemetry, String instrumentationScopeName) { + this(openTelemetry, openTelemetry.getTracer(instrumentationScopeName)); + } + + /** + * Creates a new instance of {@link Tracing}. + * + * @param openTelemetry the {@link OpenTelemetry} instance + * @param tracer the {@link Tracer} to use + */ + public Tracing(OpenTelemetry openTelemetry, Tracer tracer) { + this.openTelemetry = openTelemetry; + this.tracer = tracer; + } + + /** + * Creates a new {@link SpanBuilder} with the given span name. + * + * @param spanName the name of the span + * @return the {@link SpanBuilder} + */ + public SpanBuilder spanBuilder(String spanName) { + return tracer.spanBuilder(spanName); + } + + /** + * Runs the given {@link SpanRunnable} in a new span with the given name and with kind INTERNAL. + * + *

If an exception is thrown by the {@link SpanRunnable}, the span will be marked as error, and + * the exception will be recorded. + * + * @param spanName the name of the span + * @param runnable the {@link SpanRunnable} to run + */ + public void run(String spanName, SpanRunnable runnable) throws E { + run(tracer.spanBuilder(spanName), runnable); + } + + /** + * Runs the given {@link SpanRunnable} inside of the span created by the given {@link + * SpanBuilder}. The span will be ended at the end of the {@link SpanRunnable}. + * + *

If an exception is thrown by the {@link SpanRunnable}, the span will be marked as error, and + * the exception will be recorded. + * + * @param spanBuilder the {@link SpanBuilder} to use + * @param runnable the {@link SpanRunnable} to run + */ + @SuppressWarnings("NullAway") + public void run(SpanBuilder spanBuilder, SpanRunnable runnable) + throws E { + call( + spanBuilder, + () -> { + runnable.doInSpan(); + return null; + }); + } + + /** + * Runs the given {@link SpanCallback} inside a new span with the given name. + * + *

If an exception is thrown by the {@link SpanCallback}, the span will be marked as error, and + * the exception will be recorded. + * + * @param spanName the name of the span + * @param spanCallback the {@link SpanCallback} to call + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T call(String spanName, SpanCallback spanCallback) + throws E { + return call(tracer.spanBuilder(spanName), spanCallback); + } + + /** + * Runs the given {@link SpanCallback} inside of the span created by the given {@link + * SpanBuilder}. The span will be ended at the end of the {@link SpanCallback}. + * + *

If an exception is thrown by the {@link SpanCallback}, the span will be marked as error, and + * the exception will be recorded. + * + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T call(SpanBuilder spanBuilder, SpanCallback spanCallback) + throws E { + return call(spanBuilder, spanCallback, Tracing::setSpanError); + } + + /** + * Runs the given {@link SpanCallback} inside of the span created by the given {@link + * SpanBuilder}. The span will be ended at the end of the {@link SpanCallback}. + * + *

If an exception is thrown by the {@link SpanCallback}, the handleException consumer will be + * called, giving you the opportunity to handle the exception and span in a custom way, e.g. not + * marking the span as error. + * + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param handleException the consumer to call when an exception is thrown + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + @SuppressWarnings("NullAway") + public T call( + SpanBuilder spanBuilder, + SpanCallback spanCallback, + BiConsumer handleException) + throws E { + Span span = spanBuilder.startSpan(); + //noinspection unused + try (Scope unused = span.makeCurrent()) { + return spanCallback.doInSpan(); + } catch (Throwable e) { + handleException.accept(span, e); + throw e; + } finally { + span.end(); + } + } + + /** + * Marks a span as error. + * + * @param span the span + * @param exception the exception that caused the error + */ + private static void setSpanError(Span span, Throwable exception) { + span.setStatus(StatusCode.ERROR); + span.recordException(exception); + } + + /** + * Injects the current context into a string map, which can then be added to HTTP headers or the + * metadata of an event. + */ + public Map getTextMapPropagationContext() { + return Propagation.getTextMapPropagationContext(openTelemetry); + } + + /** + * Set baggage items inside the given {@link SpanCallback}. + * + * @param baggage the baggage items to set + * @param spanCallback the {@link SpanCallback} to call + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + @SuppressWarnings("NullAway") + public static T callWithBaggage( + Map baggage, SpanCallback spanCallback) throws E { + BaggageBuilder builder = Baggage.current().toBuilder(); + baggage.forEach(builder::put); + Context context = builder.build().storeInContext(Context.current()); + try (Scope ignore = context.makeCurrent()) { + return spanCallback.doInSpan(); + } + } + + /** + * Run the given {@link SpanCallback} inside a server span. + * + *

The span context will be extracted from the carrier, which you usually get from + * HTTP headers of the metadata of an event you're processing. + * + *

If an exception is thrown by the {@link SpanCallback}, the span will be marked as error, and + * the exception will be recorded. + * + * @param carrier the string map where to extract the span context from + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T traceServerSpan( + Map carrier, SpanBuilder spanBuilder, SpanCallback spanCallback) + throws E { + return extractAndRun(SERVER, carrier, spanBuilder, spanCallback, Tracing::setSpanError); + } + + /** + * Run the given {@link SpanCallback} inside a server span. + * + *

The span context will be extracted from the carrier, which you usually get from + * HTTP headers of the metadata of an event you're processing. + * + *

If an exception is thrown by the {@link SpanCallback}, the handleException consumer will be + * called, giving you the opportunity to handle the exception and span in a custom way, e.g. not + * marking the span as error. + * + * @param carrier the string map where to extract the span context from + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param handleException the consumer to call when an exception is thrown + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T traceServerSpan( + Map carrier, + SpanBuilder spanBuilder, + SpanCallback spanCallback, + BiConsumer handleException) + throws E { + return extractAndRun(SERVER, carrier, spanBuilder, spanCallback, handleException); + } + + /** + * Run the given {@link SpanCallback} inside a server span. + * + *

The span context will be extracted from the carrier, which you usually get from + * HTTP headers of the metadata of an event you're processing. + * + *

If an exception is thrown by the {@link SpanCallback}, the span will be marked as error, and + * the exception will be recorded. + * + * @param carrier the string map where to extract the span context from + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T traceConsumerSpan( + Map carrier, SpanBuilder spanBuilder, SpanCallback spanCallback) + throws E { + return extractAndRun(CONSUMER, carrier, spanBuilder, spanCallback, Tracing::setSpanError); + } + + /** + * Run the given {@link SpanRunnable} inside a consumer span. + * + *

The span context will be extracted from the carrier, which you usually get from + * HTTP headers of the metadata of an event you're processing. + * + *

If an exception is thrown by the {@link SpanCallback}, the handleException consumer will be + * called, giving you the opportunity to handle the exception and span in a custom way, e.g. not + * marking the span as error. + * + * @param carrier the string map where to extract the span context from + * @param spanBuilder the {@link SpanBuilder} to use + * @param spanCallback the {@link SpanCallback} to call + * @param handleException the consumer to call when an exception is thrown + * @param the type of the result + * @param the type of the exception + * @return the result of the {@link SpanCallback} + */ + public T traceConsumerSpan( + Map carrier, + SpanBuilder spanBuilder, + SpanCallback spanCallback, + BiConsumer handleException) + throws E { + return extractAndRun(CONSUMER, carrier, spanBuilder, spanCallback, handleException); + } + + private T extractAndRun( + SpanKind spanKind, + Map carrier, + SpanBuilder spanBuilder, + SpanCallback spanCallback, + BiConsumer handleException) + throws E { + try (Scope ignore = + Propagation.extractTextMapPropagationContext(openTelemetry, carrier).makeCurrent()) { + return call(spanBuilder.setSpanKind(spanKind), spanCallback, handleException); + } + } +} diff --git a/extended-tracer/src/test/java/io/opentelemetry/contrib/tracer/TracingTest.java b/extended-tracer/src/test/java/io/opentelemetry/contrib/tracer/TracingTest.java new file mode 100644 index 000000000..582582b36 --- /dev/null +++ b/extended-tracer/src/test/java/io/opentelemetry/contrib/tracer/TracingTest.java @@ -0,0 +1,200 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.tracer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.junit.jupiter.api.Named.named; + +import com.google.errorprone.annotations.Keep; +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.SemanticAttributes; +import java.util.Collections; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class TracingTest { + + interface ThrowingBiConsumer { + void accept(T t, U u) throws Throwable; + } + + @RegisterExtension + static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); + + private final Tracing tracing = new Tracing(otelTesting.getOpenTelemetry(), "test"); + + @Test + void wrapInSpan() { + assertThatIllegalStateException() + .isThrownBy( + () -> + tracing.run( + "test", + () -> { + // runs in span + throw new IllegalStateException("ex"); + })); + + String result = + tracing.call( + "another test", + () -> { + // runs in span + return "result"; + }); + assertThat(result).isEqualTo("result"); + + otelTesting + .assertTraces() + .hasSize(2) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test") + .hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + OpenTelemetryAssertions.equalTo( + SemanticAttributes.EXCEPTION_TYPE, + "java.lang.IllegalStateException"), + OpenTelemetryAssertions.satisfies( + SemanticAttributes.EXCEPTION_STACKTRACE, + string -> + string.contains( + "java.lang.IllegalStateException: ex")), + OpenTelemetryAssertions.equalTo( + SemanticAttributes.EXCEPTION_MESSAGE, "ex")))), + trace -> trace.hasSpansSatisfyingExactly(a -> a.hasName("another test"))); + } + + @Test + void propagation() { + tracing.run( + "parent", + () -> { + Map propagationHeaders = tracing.getTextMapPropagationContext(); + assertThat(propagationHeaders).hasSize(1).containsKey("traceparent"); + + tracing.traceServerSpan(propagationHeaders, tracing.spanBuilder("child"), () -> null); + }); + + otelTesting + .assertTraces() + .hasSize(1) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactly( + SpanDataAssert::hasNoParent, span -> span.hasParent(trace.getSpan(0)))); + } + + @Test + void callWithBaggage() { + String value = + tracing.call( + "parent", + () -> + Tracing.callWithBaggage( + Collections.singletonMap("key", "value"), + () -> Baggage.current().getEntryValue("key"))); + + assertThat(value).isEqualTo("value"); + } + + private static class ExtractAndRunParameter { + private final ThrowingBiConsumer> extractAndRun; + private final SpanKind wantKind; + private final StatusData wantStatus; + + private ExtractAndRunParameter( + ThrowingBiConsumer> extractAndRun, + SpanKind wantKind, + StatusData wantStatus) { + this.extractAndRun = extractAndRun; + this.wantKind = wantKind; + this.wantStatus = wantStatus; + } + } + + @Keep + private static Stream extractAndRun() { + BiConsumer ignoreException = + (span, throwable) -> { + // ignore + }; + return Stream.of( + Arguments.of( + named( + "server", + new ExtractAndRunParameter( + (t, c) -> t.traceServerSpan(Collections.emptyMap(), t.spanBuilder("span"), c), + io.opentelemetry.api.trace.SpanKind.SERVER, + io.opentelemetry.sdk.trace.data.StatusData.error()))), + Arguments.of( + named( + "server - ignore exception", + new ExtractAndRunParameter( + (t, c) -> + t.traceServerSpan( + Collections.emptyMap(), t.spanBuilder("span"), c, ignoreException), + io.opentelemetry.api.trace.SpanKind.SERVER, + io.opentelemetry.sdk.trace.data.StatusData.unset()))), + Arguments.of( + named( + "consumer", + new ExtractAndRunParameter( + (t, c) -> t.traceConsumerSpan(Collections.emptyMap(), t.spanBuilder("span"), c), + io.opentelemetry.api.trace.SpanKind.CONSUMER, + io.opentelemetry.sdk.trace.data.StatusData.error()))), + Arguments.of( + named( + "consumer - ignore exception", + new ExtractAndRunParameter( + (t, c) -> + t.traceConsumerSpan( + Collections.emptyMap(), t.spanBuilder("span"), c, ignoreException), + io.opentelemetry.api.trace.SpanKind.CONSUMER, + io.opentelemetry.sdk.trace.data.StatusData.unset())))); + } + + @ParameterizedTest + @MethodSource + void extractAndRun(ExtractAndRunParameter parameter) { + assertThatException() + .isThrownBy( + () -> + parameter.extractAndRun.accept( + tracing, + () -> { + throw new RuntimeException("ex"); + })); + + otelTesting + .assertTraces() + .hasSize(1) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasKind(parameter.wantKind).hasStatus(parameter.wantStatus))); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index dcd8914b5..4cc198498 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -71,6 +71,7 @@ include(":jfr-connection") include(":jmx-metrics") include(":maven-extension") include(":micrometer-meter-provider") +include(":extended-tracer") include(":noop-api") include(":processors") include(":prometheus-client-bridge") From 2c48b1378fc83abf4a765b652bcf4d8f855aa0e9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 17:12:32 +0000 Subject: [PATCH 099/108] Update dependency org.junit:junit-bom to v5.10.1 (#1093) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 8ab86865d..b9312f8bb 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -11,7 +11,7 @@ val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.3", "com.google.guava:guava-bom:32.1.3-jre", "com.linecorp.armeria:armeria-bom:1.26.2", - "org.junit:junit-bom:5.10.0", + "org.junit:junit-bom:5.10.1", "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", "org.testcontainers:testcontainers-bom:1.19.1" From 4a00e328fe8d40c31b2552d65faf54ff48e42c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar?= <56847527+LikeTheSalad@users.noreply.github.com> Date: Wed, 8 Nov 2023 19:07:21 +0100 Subject: [PATCH 100/108] Using android 21 as minimum supported for disk-buffering (#1096) --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index c434dbad5..c0011b976 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { api("io.opentelemetry:opentelemetry-sdk") compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") - signature("com.toasttab.android:gummy-bears-api-24:0.6.1@signature") + signature("com.toasttab.android:gummy-bears-api-21:0.6.1:coreLib@signature") testImplementation("org.mockito:mockito-inline") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") } From 07579b203fad6c5d03f5e8b05a0e7956254642b8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 07:32:53 -0800 Subject: [PATCH 101/108] Update micrometer packages to v1.12.0 (#1097) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- micrometer-meter-provider/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index c717bb03d..9bebc2242 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -19,14 +19,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.11.5") + testImplementation("io.micrometer:micrometer-core:1.12.0") } testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.11.5") + implementation("io.micrometer:micrometer-registry-prometheus:1.12.0") } } } From 6424f1713d6235f5bba1dde0500e7ad6c4aa8782 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 07:33:17 -0800 Subject: [PATCH 102/108] Update plugin com.squareup.wire to v4.9.2 (#1098) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- disk-buffering/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index c0011b976..d6465d9c8 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -5,7 +5,7 @@ plugins { id("otel.publish-conventions") id("me.champeau.jmh") version "0.7.2" id("ru.vyarus.animalsniffer") version "1.7.1" - id("com.squareup.wire") version "4.9.1" + id("com.squareup.wire") version "4.9.2" } description = "Exporter implementations that store signals on disk" From 8e347489c47e87b2cc29cd40bdba890faae466cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:17:08 -0800 Subject: [PATCH 103/108] Update dependency org.testcontainers:testcontainers-bom to v1.19.2 (#1100) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index b9312f8bb..2c3f0b238 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -14,7 +14,7 @@ val DEPENDENCY_BOMS = listOf( "org.junit:junit-bom:5.10.1", "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", - "org.testcontainers:testcontainers-bom:1.19.1" + "org.testcontainers:testcontainers-bom:1.19.2" ) val autoServiceVersion = "1.1.1" From 6e48ee09d8ea5727f0015523f0989a5d3c9b4e2a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:32:58 -0800 Subject: [PATCH 104/108] Update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v1.32.0-alpha (#1104) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 2c3f0b238..8c6fdee3c 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -13,7 +13,7 @@ val DEPENDENCY_BOMS = listOf( "com.linecorp.armeria:armeria-bom:1.26.2", "org.junit:junit-bom:5.10.1", "io.grpc:grpc-bom:1.59.0", - "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.31.0-alpha", + "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.32.0-alpha", "org.testcontainers:testcontainers-bom:1.19.2" ) From d336f4f49599a13b706b3a6ffa60258647934ab4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:33:20 -0800 Subject: [PATCH 105/108] Update dependency net.bytebuddy:byte-buddy-agent to v1.14.10 (#1106) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- runtime-attach/runtime-attach-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime-attach/runtime-attach-core/build.gradle.kts b/runtime-attach/runtime-attach-core/build.gradle.kts index f7840c1a3..fd899ee42 100644 --- a/runtime-attach/runtime-attach-core/build.gradle.kts +++ b/runtime-attach/runtime-attach-core/build.gradle.kts @@ -7,7 +7,7 @@ description = "To help in create an OpenTelemetry distro able to runtime attach otelJava.moduleName.set("io.opentelemetry.contrib.attach.core") dependencies { - implementation("net.bytebuddy:byte-buddy-agent:1.14.9") + implementation("net.bytebuddy:byte-buddy-agent:1.14.10") // Used by byte-buddy but not brought in as a transitive dependency. compileOnly("com.google.code.findbugs:annotations") From 9c1d3bf75852e800e0ad522176a0bf5e05680d86 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:34:04 -0800 Subject: [PATCH 106/108] Update dependency com.uber.nullaway:nullaway to v0.10.17 (#1105) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 8c6fdee3c..8deb5fc57 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -49,7 +49,7 @@ val DEPENDENCIES = listOf( "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "com.squareup.okhttp3:okhttp:4.12.0", - "com.uber.nullaway:nullaway:0.10.16", + "com.uber.nullaway:nullaway:0.10.17", "org.assertj:assertj-core:3.24.2", "org.awaitility:awaitility:4.2.0", "org.bouncycastle:bcpkix-jdk15on:1.70", From 870d5263b42ed896532e943f956f4e1bc0048538 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:34:22 -0800 Subject: [PATCH 107/108] Update dependency com.linecorp.armeria:armeria-bom to v1.26.3 (#1103) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 8deb5fc57..49151b910 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -10,7 +10,7 @@ rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( "com.fasterxml.jackson:jackson-bom:2.15.3", "com.google.guava:guava-bom:32.1.3-jre", - "com.linecorp.armeria:armeria-bom:1.26.2", + "com.linecorp.armeria:armeria-bom:1.26.3", "org.junit:junit-bom:5.10.1", "io.grpc:grpc-bom:1.59.0", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.32.0-alpha", From 7487fcbdc08c23003312021f31b639df0d33ed60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:25:38 -0800 Subject: [PATCH 108/108] Update dependency com.fasterxml.jackson:jackson-bom to v2.16.0 (#1101) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 49151b910..70e4df2a4 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -8,7 +8,7 @@ val dependencyVersions = hashMapOf() rootProject.extra["versions"] = dependencyVersions val DEPENDENCY_BOMS = listOf( - "com.fasterxml.jackson:jackson-bom:2.15.3", + "com.fasterxml.jackson:jackson-bom:2.16.0", "com.google.guava:guava-bom:32.1.3-jre", "com.linecorp.armeria:armeria-bom:1.26.3", "org.junit:junit-bom:5.10.1",