diff --git a/docs/instrumentation-list.yaml b/docs/instrumentation-list.yaml index 8c932158a6aa..ab45de2f1fd7 100644 --- a/docs/instrumentation-list.yaml +++ b/docs/instrumentation-list.yaml @@ -3743,12 +3743,35 @@ libraries: type: STRING hystrix: - name: hystrix-1.4 + description: This instrumentation enables the generation of INTERNAL spans for + Hystrix command executions and fallbacks. source_path: instrumentation/hystrix-1.4 scope: name: io.opentelemetry.hystrix-1.4 target_versions: javaagent: - com.netflix.hystrix:hystrix-core:[1.4.0,) + configurations: + - name: otel.instrumentation.hystrix.experimental-span-attributes + description: Enables capturing the experimental `hystrix.command`, `hystrix.circuit_open` + and `hystrix.group` span attributes. + type: boolean + default: false + telemetry: + - when: default + spans: + - span_kind: INTERNAL + attributes: [] + - when: otel.instrumentation.hystrix.experimental-span-attributes=true + spans: + - span_kind: INTERNAL + attributes: + - name: hystrix.circuit_open + type: BOOLEAN + - name: hystrix.command + type: STRING + - name: hystrix.group + type: STRING influxdb: - name: influxdb-2.4 source_path: instrumentation/influxdb-2.4 diff --git a/instrumentation-docs/instrumentations.sh b/instrumentation-docs/instrumentations.sh index 56c099e75772..cf1dae35db16 100755 --- a/instrumentation-docs/instrumentations.sh +++ b/instrumentation-docs/instrumentations.sh @@ -151,6 +151,8 @@ readonly INSTRUMENTATIONS=( "hibernate:hibernate-6.0:javaagent:testExperimental" "hibernate:hibernate-procedure-call-4.3:javaagent:test" "hibernate:hibernate-procedure-call-4.3:javaagent:testExperimental" + "hystrix-1.4:javaagent:test" + "hystrix-1.4:javaagent:testExperimental" ) # Some instrumentation test suites don't run ARM, so we use colima to run them in an x86_64 diff --git a/instrumentation/hystrix-1.4/javaagent/build.gradle.kts b/instrumentation/hystrix-1.4/javaagent/build.gradle.kts index 8a231df889e7..a5b26f2d81c6 100644 --- a/instrumentation/hystrix-1.4/javaagent/build.gradle.kts +++ b/instrumentation/hystrix-1.4/javaagent/build.gradle.kts @@ -20,13 +20,27 @@ dependencies { library("io.reactivex:rxjava:1.0.8") } -tasks.withType().configureEach { - // TODO run tests both with and without experimental span attributes - jvmArgs("-Dotel.instrumentation.hystrix.experimental-span-attributes=true") - // Disable so failure testing below doesn't inadvertently change the behavior. - jvmArgs("-Dhystrix.command.default.circuitBreaker.enabled=false") - jvmArgs("-Dio.opentelemetry.javaagent.shaded.io.opentelemetry.context.enableStrictContext=false") - - // Uncomment for debugging: - // jvmArgs("-Dhystrix.command.default.execution.timeout.enabled=false") +tasks { + withType().configureEach { + // Disable so failure testing below doesn't inadvertently change the behavior. + jvmArgs("-Dhystrix.command.default.circuitBreaker.enabled=false") + jvmArgs("-Dio.opentelemetry.javaagent.shaded.io.opentelemetry.context.enableStrictContext=false") + + systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + + // Uncomment for debugging: + // jvmArgs("-Dhystrix.command.default.execution.timeout.enabled=false") + } + + val testExperimental by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + jvmArgs("-Dotel.instrumentation.hystrix.experimental-span-attributes=true") + systemProperty("metadataConfig", "otel.instrumentation.hystrix.experimental-span-attributes=true") + } + + check { + dependsOn(testExperimental) + } } diff --git a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/ExperimentalTestHelper.java b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/ExperimentalTestHelper.java new file mode 100644 index 000000000000..f8f92b468ca9 --- /dev/null +++ b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/ExperimentalTestHelper.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hystrix; + +import static io.opentelemetry.api.common.AttributeKey.booleanKey; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + +import io.opentelemetry.api.common.AttributeKey; +import javax.annotation.Nullable; + +class ExperimentalTestHelper { + private static final boolean isEnabled = + Boolean.getBoolean("otel.instrumentation.hystrix.experimental-span-attributes"); + + static final AttributeKey HYSTRIX_COMMAND = stringKey("hystrix.command"); + static final AttributeKey HYSTRIX_GROUP = stringKey("hystrix.group"); + static final AttributeKey HYSTRIX_CIRCUIT_OPEN = booleanKey("hystrix.circuit_open"); + + @Nullable + static String experimental(String value) { + if (isEnabled) { + return value; + } + return null; + } + + @Nullable + static Boolean experimental(Boolean value) { + if (isEnabled) { + return value; + } + return null; + } + + private ExperimentalTestHelper() {} +} diff --git a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableChainTest.java b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableChainTest.java index 852d24ddba3a..32a6a9ecb7a2 100644 --- a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableChainTest.java +++ b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableChainTest.java @@ -5,8 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.hystrix; -import static io.opentelemetry.api.common.AttributeKey.booleanKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_COMMAND; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_GROUP; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.experimental; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +26,7 @@ class HystrixObservableChainTest { @RegisterExtension - protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); @Test @SuppressWarnings("RxReturnValueIgnored") @@ -93,9 +95,9 @@ protected Observable construct() { span.hasName("ExampleGroup.TestCommand.execute") .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("tracedMethod") .hasParent(trace.getSpan(1)) @@ -104,9 +106,9 @@ protected Observable construct() { span.hasName("OtherGroup.AnotherTestCommand.execute") .hasParent(trace.getSpan(1)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "AnotherTestCommand"), - equalTo(stringKey("hystrix.group"), "OtherGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("AnotherTestCommand")), + equalTo(HYSTRIX_GROUP, experimental("OtherGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("anotherTracedMethod") .hasParent(trace.getSpan(3)) diff --git a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableTest.java b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableTest.java index bc1aa3a5e00e..fc623a11ef4b 100644 --- a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableTest.java +++ b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixObservableTest.java @@ -5,8 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.hystrix; -import static io.opentelemetry.api.common.AttributeKey.booleanKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_COMMAND; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_GROUP; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.experimental; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchException; @@ -36,7 +38,7 @@ class HystrixObservableTest { @RegisterExtension - protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); @ParameterizedTest @MethodSource("provideCommandActionArguments") @@ -83,9 +85,9 @@ protected Observable construct() { span.hasName("ExampleGroup.TestCommand.execute") .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("tracedMethod") .hasParent(trace.getSpan(1)) @@ -292,9 +294,9 @@ protected Observable resumeWithFallback() { span.hasName("ExampleGroup.TestCommand.fallback") .hasParent(trace.getSpan(1)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)))); + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))))); } private static Stream provideCommandFallbackArguments() { @@ -383,17 +385,17 @@ protected Observable construct() { .hasStatus(StatusData.error()) .hasException(exception.getCause()) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "FailingGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("FailingGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("FailingGroup.TestCommand.fallback") .hasParent(trace.getSpan(1)) .hasException(hystrixRuntimeException.getFallbackException()) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "FailingGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)))); + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("FailingGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))))); } private static Stream provideCommandNoFallbackResultsInErrorArguments() { diff --git a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTest.java b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTest.java index 675a53b51f24..f87014395f03 100644 --- a/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTest.java +++ b/instrumentation/hystrix-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTest.java @@ -5,8 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.hystrix; -import static io.opentelemetry.api.common.AttributeKey.booleanKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_COMMAND; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_GROUP; +import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.experimental; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Named.named; @@ -31,7 +33,7 @@ class HystrixTest { @RegisterExtension - protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); @ParameterizedTest @MethodSource("provideCommandActionArguments") @@ -42,7 +44,7 @@ class TestCommand extends HystrixCommand { } @Override - protected String run() throws Exception { + protected String run() { return tracedMethod(); } @@ -65,9 +67,9 @@ private String tracedMethod() { span.hasName("ExampleGroup.TestCommand.execute") .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("tracedMethod") .hasParent(trace.getSpan(1)) @@ -108,16 +110,16 @@ protected String getFallback() { .hasStatus(StatusData.error()) .hasException(new IllegalArgumentException()) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)), + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))), span -> span.hasName("ExampleGroup.TestCommand.fallback") .hasParent(trace.getSpan(1)) .hasAttributesSatisfyingExactly( - equalTo(stringKey("hystrix.command"), "TestCommand"), - equalTo(stringKey("hystrix.group"), "ExampleGroup"), - equalTo(booleanKey("hystrix.circuit_open"), false)))); + equalTo(HYSTRIX_COMMAND, experimental("TestCommand")), + equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")), + equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))))); } private static Stream provideCommandActionArguments() { diff --git a/instrumentation/hystrix-1.4/metadata.yaml b/instrumentation/hystrix-1.4/metadata.yaml new file mode 100644 index 000000000000..1343efbd3737 --- /dev/null +++ b/instrumentation/hystrix-1.4/metadata.yaml @@ -0,0 +1,7 @@ +description: This instrumentation enables the generation of INTERNAL spans for Hystrix command executions and fallbacks. +configurations: + - name: otel.instrumentation.hystrix.experimental-span-attributes + description: Enables capturing the experimental `hystrix.command`, `hystrix.circuit_open` and `hystrix.group` span attributes. + type: boolean + default: false +