Hystrix metadata (#14604)

This commit is contained in:
Jay DeLuca 2025-09-09 08:02:33 -04:00 committed by GitHub
parent 5307e20028
commit aa3bd49d38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 136 additions and 45 deletions

View File

@ -3743,12 +3743,35 @@ libraries:
type: STRING type: STRING
hystrix: hystrix:
- name: hystrix-1.4 - 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 source_path: instrumentation/hystrix-1.4
scope: scope:
name: io.opentelemetry.hystrix-1.4 name: io.opentelemetry.hystrix-1.4
target_versions: target_versions:
javaagent: javaagent:
- com.netflix.hystrix:hystrix-core:[1.4.0,) - 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: influxdb:
- name: influxdb-2.4 - name: influxdb-2.4
source_path: instrumentation/influxdb-2.4 source_path: instrumentation/influxdb-2.4

View File

@ -151,6 +151,8 @@ readonly INSTRUMENTATIONS=(
"hibernate:hibernate-6.0:javaagent:testExperimental" "hibernate:hibernate-6.0:javaagent:testExperimental"
"hibernate:hibernate-procedure-call-4.3:javaagent:test" "hibernate:hibernate-procedure-call-4.3:javaagent:test"
"hibernate:hibernate-procedure-call-4.3:javaagent:testExperimental" "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 # Some instrumentation test suites don't run ARM, so we use colima to run them in an x86_64

View File

@ -20,13 +20,27 @@ dependencies {
library("io.reactivex:rxjava:1.0.8") library("io.reactivex:rxjava:1.0.8")
} }
tasks.withType<Test>().configureEach { tasks {
// TODO run tests both with and without experimental span attributes withType<Test>().configureEach {
jvmArgs("-Dotel.instrumentation.hystrix.experimental-span-attributes=true") // Disable so failure testing below doesn't inadvertently change the behavior.
// Disable so failure testing below doesn't inadvertently change the behavior. jvmArgs("-Dhystrix.command.default.circuitBreaker.enabled=false")
jvmArgs("-Dhystrix.command.default.circuitBreaker.enabled=false") jvmArgs("-Dio.opentelemetry.javaagent.shaded.io.opentelemetry.context.enableStrictContext=false")
jvmArgs("-Dio.opentelemetry.javaagent.shaded.io.opentelemetry.context.enableStrictContext=false")
// Uncomment for debugging: systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false")
// jvmArgs("-Dhystrix.command.default.execution.timeout.enabled=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)
}
} }

View File

@ -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<String> HYSTRIX_COMMAND = stringKey("hystrix.command");
static final AttributeKey<String> HYSTRIX_GROUP = stringKey("hystrix.group");
static final AttributeKey<Boolean> 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() {}
}

View File

@ -5,8 +5,10 @@
package io.opentelemetry.javaagent.instrumentation.hystrix; package io.opentelemetry.javaagent.instrumentation.hystrix;
import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN;
import static io.opentelemetry.api.common.AttributeKey.stringKey; 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 io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -24,7 +26,7 @@ import rx.schedulers.Schedulers;
class HystrixObservableChainTest { class HystrixObservableChainTest {
@RegisterExtension @RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@Test @Test
@SuppressWarnings("RxReturnValueIgnored") @SuppressWarnings("RxReturnValueIgnored")
@ -93,9 +95,9 @@ class HystrixObservableChainTest {
span.hasName("ExampleGroup.TestCommand.execute") span.hasName("ExampleGroup.TestCommand.execute")
.hasParent(trace.getSpan(0)) .hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("tracedMethod") span.hasName("tracedMethod")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
@ -104,9 +106,9 @@ class HystrixObservableChainTest {
span.hasName("OtherGroup.AnotherTestCommand.execute") span.hasName("OtherGroup.AnotherTestCommand.execute")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "AnotherTestCommand"), equalTo(HYSTRIX_COMMAND, experimental("AnotherTestCommand")),
equalTo(stringKey("hystrix.group"), "OtherGroup"), equalTo(HYSTRIX_GROUP, experimental("OtherGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("anotherTracedMethod") span.hasName("anotherTracedMethod")
.hasParent(trace.getSpan(3)) .hasParent(trace.getSpan(3))

View File

@ -5,8 +5,10 @@
package io.opentelemetry.javaagent.instrumentation.hystrix; package io.opentelemetry.javaagent.instrumentation.hystrix;
import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN;
import static io.opentelemetry.api.common.AttributeKey.stringKey; 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 io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchException; import static org.assertj.core.api.Assertions.catchException;
@ -36,7 +38,7 @@ import rx.schedulers.Schedulers;
class HystrixObservableTest { class HystrixObservableTest {
@RegisterExtension @RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@ParameterizedTest @ParameterizedTest
@MethodSource("provideCommandActionArguments") @MethodSource("provideCommandActionArguments")
@ -83,9 +85,9 @@ class HystrixObservableTest {
span.hasName("ExampleGroup.TestCommand.execute") span.hasName("ExampleGroup.TestCommand.execute")
.hasParent(trace.getSpan(0)) .hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("tracedMethod") span.hasName("tracedMethod")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
@ -292,9 +294,9 @@ class HystrixObservableTest {
span.hasName("ExampleGroup.TestCommand.fallback") span.hasName("ExampleGroup.TestCommand.fallback")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)))); equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false)))));
} }
private static Stream<Arguments> provideCommandFallbackArguments() { private static Stream<Arguments> provideCommandFallbackArguments() {
@ -383,17 +385,17 @@ class HystrixObservableTest {
.hasStatus(StatusData.error()) .hasStatus(StatusData.error())
.hasException(exception.getCause()) .hasException(exception.getCause())
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "FailingGroup"), equalTo(HYSTRIX_GROUP, experimental("FailingGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("FailingGroup.TestCommand.fallback") span.hasName("FailingGroup.TestCommand.fallback")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
.hasException(hystrixRuntimeException.getFallbackException()) .hasException(hystrixRuntimeException.getFallbackException())
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "FailingGroup"), equalTo(HYSTRIX_GROUP, experimental("FailingGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)))); equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false)))));
} }
private static Stream<Arguments> provideCommandNoFallbackResultsInErrorArguments() { private static Stream<Arguments> provideCommandNoFallbackResultsInErrorArguments() {

View File

@ -5,8 +5,10 @@
package io.opentelemetry.javaagent.instrumentation.hystrix; package io.opentelemetry.javaagent.instrumentation.hystrix;
import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.javaagent.instrumentation.hystrix.ExperimentalTestHelper.HYSTRIX_CIRCUIT_OPEN;
import static io.opentelemetry.api.common.AttributeKey.stringKey; 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 io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Named.named; import static org.junit.jupiter.api.Named.named;
@ -31,7 +33,7 @@ import org.junit.jupiter.params.provider.MethodSource;
class HystrixTest { class HystrixTest {
@RegisterExtension @RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@ParameterizedTest @ParameterizedTest
@MethodSource("provideCommandActionArguments") @MethodSource("provideCommandActionArguments")
@ -42,7 +44,7 @@ class HystrixTest {
} }
@Override @Override
protected String run() throws Exception { protected String run() {
return tracedMethod(); return tracedMethod();
} }
@ -65,9 +67,9 @@ class HystrixTest {
span.hasName("ExampleGroup.TestCommand.execute") span.hasName("ExampleGroup.TestCommand.execute")
.hasParent(trace.getSpan(0)) .hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("tracedMethod") span.hasName("tracedMethod")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
@ -108,16 +110,16 @@ class HystrixTest {
.hasStatus(StatusData.error()) .hasStatus(StatusData.error())
.hasException(new IllegalArgumentException()) .hasException(new IllegalArgumentException())
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)), equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false))),
span -> span ->
span.hasName("ExampleGroup.TestCommand.fallback") span.hasName("ExampleGroup.TestCommand.fallback")
.hasParent(trace.getSpan(1)) .hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(
equalTo(stringKey("hystrix.command"), "TestCommand"), equalTo(HYSTRIX_COMMAND, experimental("TestCommand")),
equalTo(stringKey("hystrix.group"), "ExampleGroup"), equalTo(HYSTRIX_GROUP, experimental("ExampleGroup")),
equalTo(booleanKey("hystrix.circuit_open"), false)))); equalTo(HYSTRIX_CIRCUIT_OPEN, experimental(false)))));
} }
private static Stream<Arguments> provideCommandActionArguments() { private static Stream<Arguments> provideCommandActionArguments() {

View File

@ -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