-
Notifications
You must be signed in to change notification settings - Fork 979
Description
Describe the bug
When integrating hbase-client versions 1.0.0 to 1.7.2, the hbase-client depends on protobuf-java version 2.x. However, the getExportedSpans method in AgentTestRunner uses protobuf-java for deserialization, but it relies on protobuf-java version 3.x. This leads to a conflict between the LiteralByteString class from version 2.x and the GeneratedMessageV3 class from version 3.x.
Steps to reproduce
Add the dependency testImplementation("org.apache.hbase:hbase-client:1.4.0"), and then execute the following code:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class HbaseClient140Test {
private static final Integer MASTER_PORT = 16000;
private static final Integer REGION_SERVER_PORT = 16020;
private static final String NAMESPACE = "ot_test";
private static final byte[] COLUMN_FAMILY = Bytes.toBytes("cf");
private static final TableName TABLE_NAME = TableName.valueOf("ot_test:eleven_test_table");
private static final TableName META = TableName.valueOf("hbase:meta");
private static final String DB_SYSTEM = "HBase";
private static final String SCAN = "Scan";
private static final String MUTATE = "Mutate";
private static final String GET = "Get";
private static final String MULTI = "Multi";
private static final String HOSTNAME = getHostName();
@RegisterExtension
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
private static final GenericContainer<?> hbaseContainer =
new GenericContainer<>(DockerImageName.parse("harisekhon/hbase:2.0"))
.withCreateContainerCmdModifier(
cmd -> {
cmd.getHostConfig()
.withPortBindings(
new PortBinding(Ports.Binding.bindPort(2181), new ExposedPort(2181)),
new PortBinding(Ports.Binding.bindPort(16000), new ExposedPort(16000)),
new PortBinding(Ports.Binding.bindPort(16010), new ExposedPort(16010)),
new PortBinding(Ports.Binding.bindPort(16020), new ExposedPort(16020)),
new PortBinding(Ports.Binding.bindPort(16030), new ExposedPort(16030)),
new PortBinding(Ports.Binding.bindPort(16201), new ExposedPort(16201)),
new PortBinding(Ports.Binding.bindPort(16301), new ExposedPort(16301)));
})
.withExposedPorts(2181, 16000, 16010, 16020, 16030, 16201, 16301)
.withCreateContainerCmdModifier(cmd -> cmd.withHostName(HOSTNAME))
.waitingFor(Wait.forListeningPort())
.waitingFor(Wait.forLogMessage(".Master has completed initialization.\n", 1));
private static Connection connection;
private static String getHostName() {
InetAddress localHost = null;
try {
localHost = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
return null;
}
return localHost.getHostName();
}
@BeforeAll
static void setupSpec() {
hbaseContainer.start();
String host = hbaseContainer.getHost();
Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", host);
config.set("hbase.zookeeper.property.clientPort", "2181");
Exception error = null;
try {
connection = ConnectionFactory.createConnection(config);
} catch (IOException e) {
error = e;
}
assertNull(error);
}
@afterall
static void cleanupSpec() {
hbaseContainer.stop();
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@beforeeach
void setup() {
testing.clearData();
}
@test
@order(1)
public void createNameBaseTest() {
Exception error = null;
boolean namespaceCreateStatus;
try {
Admin admin = connection.getAdmin();
NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(NAMESPACE).build();
admin.createNamespace(namespaceDescriptor);
namespaceCreateStatus = true;
admin.close();
} catch (IOException e) {
namespaceCreateStatus = false;
error = e;
}
assertNull(error);
assertTrue(namespaceCreateStatus);
}
@test
@order(2)
public void listNamespaceTest() throws InterruptedException {
Exception error = null;
boolean namespaceExists = false;
try {
Admin admin = connection.getAdmin();
for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) {
if (ns.getName().equals(NAMESPACE)) {
namespaceExists = true;
}
}
admin.close();
} catch (IOException e) {
error = e;
}
assertNull(error);
assertTrue(namespaceExists);
testing.waitAndAssertTraces(
traceAssertConsumer(null, "IsMasterRunning", MASTER_PORT, false),
traceAssertConsumer(null, "ListNamespaceDescriptors", MASTER_PORT, false));
}
private static Consumer traceAssertConsumer(
TableName table, String operation, int port, boolean hasTable) {
List assertions = new ArrayList<>();
assertions.add(equalTo(SemanticAttributes.DB_SYSTEM, DB_SYSTEM));
assertions.add(equalTo(SemanticAttributes.DB_OPERATION, operation));
if (hasTable) {
assertions.add(equalTo(SemanticAttributes.DB_NAME, table.getNameAsString()));
}
assertions.add(equalTo(SemanticAttributes.NET_PEER_NAME, HOSTNAME));
assertions.add(equalTo(SemanticAttributes.NET_PEER_PORT, port));
assertions.add(satisfies(SemanticAttributes.DB_USER, AbstractAssert::isNotNull));
String spanName = operation + (hasTable ? " " + table.getNameAsString() : "");
return trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName(spanName)
.hasKind(SpanKind.CLIENT)
.hasAttributesSatisfyingExactly(assertions));
}
}
Expected behavior
Expected the test class to execute successfully.
Actual behavior
Using protobuf-java:2.5.0 will result in a java.lang.NoClassDefFoundError: com/google/protobuf/GeneratedMessageV3 exception, while using the default 3.x version will result in a java.lang.NoClassDefFoundError: com/google/protobuf/LiteralByteString.
Javaagent or library instrumentation version
Integrated HBase version 1.4.0 myself, but haven't submitted the PR yet.
Environment
JDK:
OS:
Additional context
No response