diff --git a/benchmarks/src/test/java/zipkin2/server/ServerIntegratedBenchmark.java b/benchmarks/src/test/java/zipkin2/server/ServerIntegratedBenchmark.java index 7eeb4773cb1..bd924a53a56 100644 --- a/benchmarks/src/test/java/zipkin2/server/ServerIntegratedBenchmark.java +++ b/benchmarks/src/test/java/zipkin2/server/ServerIntegratedBenchmark.java @@ -91,7 +91,7 @@ class ServerIntegratedBenchmark { @Test void elasticsearch() throws Exception { GenericContainer elasticsearch = - new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-elasticsearch7:3.0.4")) + new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-elasticsearch7:3.0.5")) .withNetwork(Network.SHARED) .withNetworkAliases("elasticsearch") .withLabel("name", "elasticsearch") @@ -105,7 +105,7 @@ class ServerIntegratedBenchmark { @Test void cassandra3() throws Exception { GenericContainer cassandra = - new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-cassandra:3.0.4")) + new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-cassandra:3.0.5")) .withNetwork(Network.SHARED) .withNetworkAliases("cassandra") .withLabel("name", "cassandra") @@ -119,7 +119,7 @@ class ServerIntegratedBenchmark { @Test void mysql() throws Exception { GenericContainer mysql = - new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-mysql:3.0.4")) + new GenericContainer<>(parse("ghcr.io/openzipkin/zipkin-mysql:3.0.5")) .withNetwork(Network.SHARED) .withNetworkAliases("mysql") .withLabel("name", "mysql") diff --git a/zipkin-collector/activemq/src/test/java/zipkin2/collector/activemq/ActiveMQExtension.java b/zipkin-collector/activemq/src/test/java/zipkin2/collector/activemq/ActiveMQExtension.java index 9072fd11edb..cb6e0578703 100644 --- a/zipkin-collector/activemq/src/test/java/zipkin2/collector/activemq/ActiveMQExtension.java +++ b/zipkin-collector/activemq/src/test/java/zipkin2/collector/activemq/ActiveMQExtension.java @@ -64,7 +64,7 @@ String brokerURL() { // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 static final class ActiveMQContainer extends GenericContainer { ActiveMQContainer() { - super(parse("ghcr.io/openzipkin/zipkin-activemq:3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-activemq:3.0.5")); withExposedPorts(ACTIVEMQ_PORT); waitStrategy = Wait.forListeningPorts(ACTIVEMQ_PORT); withStartupTimeout(Duration.ofSeconds(60)); diff --git a/zipkin-collector/kafka/src/test/java/zipkin2/collector/kafka/KafkaExtension.java b/zipkin-collector/kafka/src/test/java/zipkin2/collector/kafka/KafkaExtension.java index d3ac12e89b2..381dbc9d0a8 100644 --- a/zipkin-collector/kafka/src/test/java/zipkin2/collector/kafka/KafkaExtension.java +++ b/zipkin-collector/kafka/src/test/java/zipkin2/collector/kafka/KafkaExtension.java @@ -92,7 +92,7 @@ KafkaCollector.Builder newCollectorBuilder(String topic, int streams) { // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 static final class KafkaContainer extends GenericContainer { KafkaContainer() { - super(parse("ghcr.io/openzipkin/zipkin-kafka:3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-kafka:3.0.5")); waitStrategy = Wait.forHealthcheck(); // 19092 is for connections from the Docker host and needs to be used as a fixed port. // TODO: someone who knows Kafka well, make ^^ comment better! diff --git a/zipkin-collector/rabbitmq/src/test/java/zipkin2/collector/rabbitmq/RabbitMQExtension.java b/zipkin-collector/rabbitmq/src/test/java/zipkin2/collector/rabbitmq/RabbitMQExtension.java index 1f1475228e5..92522859c53 100644 --- a/zipkin-collector/rabbitmq/src/test/java/zipkin2/collector/rabbitmq/RabbitMQExtension.java +++ b/zipkin-collector/rabbitmq/src/test/java/zipkin2/collector/rabbitmq/RabbitMQExtension.java @@ -83,7 +83,7 @@ int port() { // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 static final class RabbitMQContainer extends GenericContainer { RabbitMQContainer() { - super(parse("ghcr.io/openzipkin/zipkin-rabbitmq:3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-rabbitmq:3.0.5")); withExposedPorts(RABBIT_PORT); waitStrategy = Wait.forLogMessage(".*Server startup complete.*", 1); withStartupTimeout(Duration.ofSeconds(60)); diff --git a/zipkin-server/src/test/java/zipkin2/server/internal/eureka/BaseITZipkinEureka.java b/zipkin-server/src/test/java/zipkin2/server/internal/eureka/BaseITZipkinEureka.java index cdb930ef8e4..5434787a56d 100644 --- a/zipkin-server/src/test/java/zipkin2/server/internal/eureka/BaseITZipkinEureka.java +++ b/zipkin-server/src/test/java/zipkin2/server/internal/eureka/BaseITZipkinEureka.java @@ -141,7 +141,7 @@ static final class EurekaContainer extends GenericContainer { static final int EUREKA_PORT = 8761; EurekaContainer(Map env) { - super(parse("ghcr.io/openzipkin/zipkin-eureka:3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-eureka:3.0.5")); withEnv(env); withExposedPorts(EUREKA_PORT); waitStrategy = Wait.forHealthcheck(); diff --git a/zipkin-storage/cassandra/README.md b/zipkin-storage/cassandra/README.md index 8173207ff28..463856b2a9f 100644 --- a/zipkin-storage/cassandra/README.md +++ b/zipkin-storage/cassandra/README.md @@ -150,7 +150,7 @@ As you'll notice, the duration component is optional, and stored in millisecond resolution as opposed to microsecond (which the query represents). The final query shows that the input is rounded up to the nearest millisecond. -The reason we can query on `duration` is due to a SASI index. Eventhough the +The reason we can query on `duration` is due to a SASI index. Even though the search granularity is millisecond, original duration data remains microsecond granularity. Meanwhile, write performance is dramatically better than writing discrete values, due to fewer distinct writes. @@ -175,6 +175,6 @@ optimised for queries within a single day. The penalty of reading multiple days otherwise overhead of reading a significantly larger amount of data. ### Benchmarking -Benchmarking the new datamodel demonstrates a significant performance improvement on reads. How much of this translates to the +Benchmarking the new data model demonstrates a significant performance improvement on reads. How much of this translates to the Zipkin UI is hard to tell due to the complexity of CassandraSpanConsumer and how searches are possible. Benchmarking stress profiles are found in traces-stress.yaml and trace_by_service_span-stress.yaml and span_by_service-stress.yaml. diff --git a/zipkin-storage/cassandra/pom.xml b/zipkin-storage/cassandra/pom.xml index 73a5f3d3ead..b9e04d85cb0 100644 --- a/zipkin-storage/cassandra/pom.xml +++ b/zipkin-storage/cassandra/pom.xml @@ -73,8 +73,8 @@ org.apache.cassandra java-driver-core ${java-driver.version} - + com.esri.geometry * @@ -92,6 +92,16 @@ Mockito dies trying to mock CqlSession without it. --> + + + + org.slf4j + slf4j-api + ${slf4j.version} + provided + + com.github.jnr diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraAutocompleteTags.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraAutocompleteTags.java index b3add5aac73..3c254806474 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraAutocompleteTags.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraAutocompleteTags.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -13,8 +13,6 @@ */ package zipkin2.storage.cassandra; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import zipkin2.Call; import zipkin2.storage.AutocompleteTags; @@ -28,7 +26,7 @@ class CassandraAutocompleteTags implements AutocompleteTags { enabled = storage.searchEnabled && !storage.autocompleteKeys.isEmpty() && storage.metadata().hasAutocompleteTags; - keysCall = Call.create(Collections.unmodifiableList(new ArrayList<>(storage.autocompleteKeys))); + keysCall = Call.create(List.copyOf(storage.autocompleteKeys)); valuesCallFactory = enabled ? new SelectAutocompleteValues.Factory(storage.session()) : null; } diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanConsumer.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanConsumer.java index e0666ea497f..4ec15e410b4 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanConsumer.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -36,8 +36,7 @@ import static zipkin2.storage.cassandra.Schema.TABLE_SERVICE_SPANS; class CassandraSpanConsumer implements SpanConsumer { // not final for testing - final CqlSession session; - final boolean strictTraceId, searchEnabled; + final boolean searchEnabled; final InsertSpan.Factory insertSpan; final Set autocompleteKeys; @@ -62,12 +61,9 @@ void clear() { ); } - // Exposed to allow tests to switch from strictTraceId to not CassandraSpanConsumer(CqlSession session, Schema.Metadata metadata, boolean strictTraceId, boolean searchEnabled, Set autocompleteKeys, int autocompleteTtl, int autocompleteCardinality) { - this.session = session; - this.strictTraceId = strictTraceId; this.searchEnabled = searchEnabled; this.autocompleteKeys = autocompleteKeys; diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanStore.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanStore.java index 527474a9588..a2a04a6a0c4 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanStore.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraSpanStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -166,7 +166,7 @@ static SelectTraceIdsFromSpan.Factory initialiseSelectTraceIdsFromSpan(CqlSessio * Creates a call representing one or more queries against {@link Schema#TABLE_TRACE_BY_SERVICE_SPAN} * and possibly {@link Schema#TABLE_TRACE_BY_SERVICE_REMOTE_SERVICE}. * - *

The result will be an aggregate if the input requests's serviceName is null, both span name + *

The result will be an aggregate if the input request serviceName is null, both span name * and remote service name are supplied, or there's more than one day of data in the timestamp * range. * @@ -226,7 +226,7 @@ Call> newBucketedTraceIdCall( traceIndexFetchSize)); } - if ("".equals(serviceName)) { + if (serviceName.isEmpty()) { // If we have no service name, we have to lookup service names before running trace ID queries Call> serviceNames = getServiceNames(); if (serviceRemoteServices.isEmpty()) { diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraStorage.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraStorage.java index deeb61c28c9..c5e5724d337 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraStorage.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraStorage.java @@ -206,7 +206,7 @@ Schema.Metadata metadata() { return ResultSetFutureCall.isOverCapacity(e); } - @Override public final String toString() { + @Override public String toString() { return "CassandraStorage{contactPoints=" + contactPoints + ", keyspace=" + keyspace + "}"; } diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraUtil.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraUtil.java index 8f85453887a..fa5bb489964 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraUtil.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -60,7 +60,7 @@ public static int durationIndexBucket(long ts_micro) { *

Values over {@link RecyclableBuffers#SHORT_STRING_LENGTH} are not considered. Zipkin's * {@link QueryRequest#annotationQuery()} are equals match. Not all values are lookup values. For * example, {@code sql.query} isn't something that is likely to be looked up by value and indexing - * that could add a potentially kilobyte partition key on {@link Schema#TABLE_SPAN} + * that could add a kilobyte partition key on {@link Schema#TABLE_SPAN} * * @see QueryRequest#annotationQuery() */ diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/InsertSpan.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/InsertSpan.java index e624fb64410..291e43c10b0 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/InsertSpan.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/InsertSpan.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -129,7 +129,7 @@ Call create(Input span) { *

If there's consistently 8 tombstones (nulls) per row, then we'll only need 125 spans in a * trace (rows in a partition) to trigger the `tombstone_warn_threshold warnings being logged in * the C* nodes. And if we go to 12500 spans in a trace then that whole trace partition would - * become unreadable. Cassandra warns at a 1000 tombstones in any query, and fails on 100000 + * become unreadable. Cassandra warns at 1000 tombstones in any query, and fails on 100000 * tombstones. * *

There's also a small question about disk usage efficiency. Each tombstone is a cell name @@ -143,8 +143,8 @@ Call create(Input span) { *

Another popular practice is to insert those potentially null columns as separate statements * (and optionally put them together into UNLOGGED batches). This works as multiple writes to the * same partition has little overhead, and here we're not worried about lack of isolation between - * those writes, as the write is asynchronous anyway. An example of this approach is in the - * cassandra-reaper project here: https://github.com/thelastpickle/cassandra-reaper/blob/master/src/server/src/main/java/io/cassandrareaper/storage/CassandraStorage.java#L622-L642 + * writes, as it is asynchronous anyway. An example of this approach is in the cassandra-reaper + * project here: https://github.com/thelastpickle/cassandra-reaper/blob/master/src/server/src/main/java/io/cassandrareaper/storage/CassandraStorage.java#L622-L642 */ @Override protected CompletionStage newCompletionStage() { BoundStatementBuilder bound = factory.preparedStatement.boundStatementBuilder() diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/LazySession.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/LazySession.java index 2614543ad5f..97fe2039547 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/LazySession.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/LazySession.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -15,7 +15,6 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.PreparedStatement; -import com.datastax.oss.driver.api.core.cql.ResultSet; import zipkin2.storage.cassandra.CassandraStorage.SessionFactory; import static zipkin2.storage.cassandra.Schema.TABLE_SPAN; @@ -51,9 +50,9 @@ Schema.Metadata metadata() { return metadata; } - ResultSet healthCheck() { + void healthCheck() { get(); - return session.execute(healthCheck.bind()); + session.execute(healthCheck.bind()); } void close() { diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/Schema.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/Schema.java index 32b06dd2cae..33bc1fef996 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/Schema.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/Schema.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -19,7 +19,6 @@ import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata; import java.util.Map; import java.util.UUID; -import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -105,7 +104,7 @@ static Version ensureVersion(com.datastax.oss.driver.api.core.metadata.Metadata return version; } - static KeyspaceMetadata ensureExists(String keyspace, boolean searchEnabled, CqlSession session) { + static void ensureExists(String keyspace, boolean searchEnabled, CqlSession session) { KeyspaceMetadata result = session.getMetadata().getKeyspace(keyspace).orElse(null); if (result == null || result.getTable(Schema.TABLE_SPAN).isEmpty()) { LOG.info("Installing schema {} for keyspace {}", SCHEMA_RESOURCE, keyspace); @@ -125,7 +124,6 @@ static KeyspaceMetadata ensureExists(String keyspace, boolean searchEnabled, Cql LOG.info("Upgrading schema {}", UPGRADE_2); applyCqlFile(keyspace, session, UPGRADE_2); } - return result; } static boolean hasUpgrade1_autocompleteTags(KeyspaceMetadata keyspaceMetadata) { diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/SelectServiceNames.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/SelectServiceNames.java index 0efef5aff34..810600cb1fa 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/SelectServiceNames.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/SelectServiceNames.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -32,7 +32,7 @@ static final class Factory { Factory(CqlSession session) { this.session = session; this.preparedStatement = session.prepare("SELECT DISTINCT service" - + " FROM " + TABLE_SERVICE_SPANS); + + " FROM " + TABLE_SERVICE_SPANS); } Call> create() { diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/SessionBuilder.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/SessionBuilder.java index 09c8a2402e1..d865b971c01 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/SessionBuilder.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/SessionBuilder.java @@ -35,7 +35,7 @@ import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_LOGGER_SUCCESS_ENABLED; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_LOGGER_VALUES; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_TIMEOUT; -import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_TRACKER_CLASS; +import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_TRACKER_CLASSES; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_WARN_IF_SET_KEYSPACE; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_HOSTNAME_VALIDATION; @@ -86,7 +86,7 @@ public static CqlSession buildSession( // Log categories can enable query logging Logger requestLogger = LoggerFactory.getLogger(SessionBuilder.class); if (requestLogger.isDebugEnabled()) { - config = config.withClass(REQUEST_TRACKER_CLASS, RequestLogger.class); + config = config.withClassList(REQUEST_TRACKER_CLASSES, List.of(RequestLogger.class)); config = config.withBoolean(REQUEST_LOGGER_SUCCESS_ENABLED, true); // Only show bodies when TRACE is enabled config = config.withBoolean(REQUEST_LOGGER_VALUES, requestLogger.isTraceEnabled()); diff --git a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsert.java b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsert.java index 1c0588363d6..dc0300509eb 100644 --- a/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsert.java +++ b/zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsert.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -60,7 +60,7 @@ protected DeduplicatingInsert(DelayLimiter delayLimiter, I input) { } @Override protected final void doEnqueue(Callback callback) { - super.doEnqueue(new Callback() { + super.doEnqueue(new Callback<>() { @Override public void onSuccess(Void value) { callback.onSuccess(value); } diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraStorageExtension.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraContainer.java similarity index 78% rename from zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraStorageExtension.java rename to zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraContainer.java index 439956ab405..dab856edb29 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraStorageExtension.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/CassandraContainer.java @@ -23,10 +23,6 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import org.junit.jupiter.api.extension.AfterAllCallback; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.opentest4j.TestAbortedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.GenericContainer; @@ -41,19 +37,19 @@ import static zipkin2.storage.cassandra.Schema.TABLE_DEPENDENCY; import static zipkin2.storage.cassandra.Schema.TABLE_SPAN; -public class CassandraStorageExtension implements BeforeAllCallback, AfterAllCallback { - static final Logger LOGGER = LoggerFactory.getLogger(CassandraStorageExtension.class); - - final CassandraContainer container = new CassandraContainer(); +class CassandraContainer extends GenericContainer { + static final Logger LOGGER = LoggerFactory.getLogger(CassandraContainer.class); CqlSession globalSession; - @Override public void beforeAll(ExtensionContext context) { - if (context.getRequiredTestClass().getEnclosingClass() != null) { - // Only run once in outermost scope. - return; - } + CassandraContainer() { + super(parse("ghcr.io/openzipkin/zipkin-cassandra:3.0.5")); + addExposedPort(9042); + waitStrategy = Wait.forHealthcheck(); + withLogConsumer(new Slf4jLogConsumer(LOGGER)); + } - container.start(); + @Override public void start() { + super.start(); LOGGER.info("Using contactPoint {}", contactPoint()); globalSession = tryToInitializeSession(contactPoint()); } @@ -82,7 +78,7 @@ static CassandraStorage.Builder newStorageBuilder(String contactPoint) { } String contactPoint() { - return container.getHost() + ":" + container.getMappedPort(9042); + return getHost() + ":" + getMappedPort(9042); } void clear(CassandraStorage storage) { @@ -108,12 +104,9 @@ void clear(CassandraStorage storage) { blockWhileInFlight(storage); } - @Override public void afterAll(ExtensionContext context) { - if (context.getRequiredTestClass().getEnclosingClass() != null) { - // Only run once in outermost scope. - return; - } + @Override public void stop() { if (globalSession != null) globalSession.close(); + super.stop(); } static void blockWhileInFlight(CassandraStorage storage) { @@ -152,14 +145,4 @@ static boolean poolInFlight(CqlSession session) { } return false; } - - // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 - static final class CassandraContainer extends GenericContainer { - CassandraContainer() { - super(parse("ghcr.io/openzipkin/zipkin-cassandra:3.0.4")); - addExposedPort(9042); - waitStrategy = Wait.forHealthcheck(); - withLogConsumer(new Slf4jLogConsumer(LOGGER)); - } - } } diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorage.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorage.java index 1a31e47e244..8840146f5dd 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorage.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorage.java @@ -21,8 +21,8 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.extension.RegisterExtension; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import zipkin2.Span; import zipkin2.storage.StorageComponent.Builder; @@ -34,7 +34,7 @@ import static zipkin2.storage.cassandra.Schema.TABLE_TRACE_BY_SERVICE_REMOTE_SERVICE; import static zipkin2.storage.cassandra.Schema.TABLE_TRACE_BY_SERVICE_SPAN; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Testcontainers @Tag("docker") class ITCassandraStorage { static final List SEARCH_TABLES = asList( @@ -45,7 +45,7 @@ class ITCassandraStorage { TABLE_TRACE_BY_SERVICE_SPAN ); - @RegisterExtension CassandraStorageExtension cassandra = new CassandraStorageExtension(); + @Container static CassandraContainer cassandra = new CassandraContainer(); @Nested class ITTraces extends zipkin2.storage.ITTraces { @@ -60,7 +60,7 @@ public void getTrace_deduplicates(TestInfo testInfo) { } @Override protected void blockWhileInFlight() { - CassandraStorageExtension.blockWhileInFlight(storage); + CassandraContainer.blockWhileInFlight(storage); } @Override public void clear() { @@ -75,7 +75,7 @@ class ITSpanStore extends zipkin2.storage.ITSpanStore { } @Override protected void blockWhileInFlight() { - CassandraStorageExtension.blockWhileInFlight(storage); + CassandraContainer.blockWhileInFlight(storage); } @Override public void clear() { @@ -90,7 +90,7 @@ class ITSearchEnabledFalse extends zipkin2.storage.ITSearchEnabledFalse { } @Override protected void blockWhileInFlight() { - CassandraStorageExtension.blockWhileInFlight(storage); + CassandraContainer.blockWhileInFlight(storage); } @Override public void clear() { @@ -203,7 +203,7 @@ class ITSpanConsumer extends zipkin2.storage.cassandra.ITSpanConsumer { } @Override protected void blockWhileInFlight() { - CassandraStorageExtension.blockWhileInFlight(storage); + CassandraContainer.blockWhileInFlight(storage); } @Override public void clear() { diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorageHeavy.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorageHeavy.java index 2ba36bffcfd..a094f1a2702 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorageHeavy.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITCassandraStorageHeavy.java @@ -20,8 +20,8 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.extension.RegisterExtension; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import zipkin2.Span; import zipkin2.storage.QueryRequest; @@ -36,16 +36,16 @@ /** * Large amounts of writes can make other tests flake. This can happen for reasons such as * overloading the test Cassandra container or knock-on effects of tombstones left from {@link - * CassandraStorageExtension#clear(CassandraStorage)}. + * CassandraContainer#clear(CassandraStorage)}. * *

Tests here share a different Cassandra container and each method runs in an isolated * keyspace. As schema installation takes ~10s, hesitate adding too many tests here. */ -@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Testcontainers @Tag("docker") class ITCassandraStorageHeavy { - @RegisterExtension CassandraStorageExtension backend = new CassandraStorageExtension(); + @Container static CassandraContainer backend = new CassandraContainer(); @Nested class ITSpanStoreHeavy extends zipkin2.storage.ITSpanStoreHeavy { @@ -54,7 +54,7 @@ class ITSpanStoreHeavy extends zipkin2.storage.ITSpanStoreHeavy { @Override protected void configureStorageForTest(StorageComponent.Builder storage) { ((CassandraStorage.Builder) storage) - .ensureSchema(false).autocompleteKeys(asList("environment")); + .ensureSchema(false).autocompleteKeys(List.of("environment")); } @Override protected boolean initializeStoragePerTest() { diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITSpanConsumer.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITSpanConsumer.java index dcd0e9a91d1..edeb3a29507 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITSpanConsumer.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITSpanConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -34,7 +34,7 @@ abstract class ITSpanConsumer extends ITStorage { @Override protected void configureStorageForTest(StorageComponent.Builder storage) { - storage.autocompleteKeys(asList("environment")); + storage.autocompleteKeys(List.of("environment")); } /** @@ -65,7 +65,8 @@ abstract class ITSpanConsumer extends ITStorage { .name("get") .kind(Span.Kind.CLIENT) .localEndpoint(trace[0].localEndpoint()) - .timestamp(trace[0].timestampAsLong() + i * 1000) // all peer span timestamps happen 1ms later + .timestamp( + trace[0].timestampAsLong() + i * 1000L) // all peer span timestamps happen 1ms later .duration(10L) .build()); @@ -105,7 +106,8 @@ abstract class ITSpanConsumer extends ITStorage { .localEndpoint(trace[0].localEndpoint()) .putTag("environment", "dev") .putTag("a", "b") - .timestamp(trace[0].timestampAsLong() + i * 1000) // all peer span timestamps happen 1ms later + .timestamp( + trace[0].timestampAsLong() + i * 1000L) // all peer span timestamps happen 1ms later .duration(10L) .build()); @@ -120,10 +122,8 @@ abstract class ITSpanConsumer extends ITStorage { /** It is easier to use a real Cassandra connection than mock a prepared statement. */ @Test void insertEntry_niceToString() { // This test can use fake data as it is never written to cassandra - Span clientSpan = CLIENT_SPAN; - AggregateCall acceptCall = - (AggregateCall) storage.spanConsumer().accept(asList(clientSpan)); + (AggregateCall) storage.spanConsumer().accept(List.of(CLIENT_SPAN)); List> insertEntryCalls = acceptCall.delegate().stream() .filter(c -> c instanceof InsertEntry) @@ -155,7 +155,7 @@ static long rowCountForTags(CassandraStorage storage) { static String getTagValue(CassandraStorage storage, String key) { return storage .session() - .execute("SELECT value from " + Schema.TABLE_AUTOCOMPLETE_TAGS + " WHERE key='environment'") + .execute("SELECT value from " + Schema.TABLE_AUTOCOMPLETE_TAGS + " WHERE key='" + key + "'") .one() .getString(0); } diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/SchemaTest.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/SchemaTest.java index 7f85d7c4095..c396d249200 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/SchemaTest.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/SchemaTest.java @@ -141,7 +141,7 @@ PRIMARY KEY (service, remote_service) @Test void reviseCql_removes_dclocal_read_repair_chance_on_v4() { assertThat(Schema.reviseCQL(Version.V4_0_0, schemaWithReadRepair)) - // literal used to show newlines etc are in-tact + // literal used to show newlines etc. are in-tact .isEqualTo(""" CREATE TABLE IF NOT EXISTS zipkin2.remote_service_by_service ( service text, diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/HostAndPortTest.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/HostAndPortTest.java index 3922b01851b..47a2e279628 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/HostAndPortTest.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/HostAndPortTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -27,10 +27,8 @@ class HostAndPortTest { "google.com", "192.0.2.1", "2001::3" - ).forEach(host -> { - assertThat(HostAndPort.fromString(host, 77)) - .isEqualTo(new HostAndPort(host, 77)); - }); + ).forEach(host -> assertThat(HostAndPort.fromString(host, 77)) + .isEqualTo(new HostAndPort(host, 77))); } @Test void parsesHost_emptyPortOk() { diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsertTest.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsertTest.java index 8573a097f70..9f2b66012ce 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsertTest.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/DeduplicatingInsertTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -46,7 +46,7 @@ class DeduplicatingInsertTest { assertThat(testFactory.values).containsExactly("foo", "bar"); } - Callback assertFailOnError = new Callback() { + Callback assertFailOnError = new Callback<>() { @Override public void onSuccess(Void value) { } diff --git a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/ResultSetFutureCallTest.java b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/ResultSetFutureCallTest.java index 21451efb655..36d7a459c1a 100644 --- a/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/ResultSetFutureCallTest.java +++ b/zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/internal/call/ResultSetFutureCallTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenZipkin Authors + * Copyright 2015-2024 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -31,7 +31,7 @@ class ResultSetFutureCallTest { CompletableFuture future = new CompletableFuture<>(); AsyncResultSet resultSet = mock(AsyncResultSet.class); - ResultSetFutureCall call = new ResultSetFutureCall() { + ResultSetFutureCall call = new ResultSetFutureCall<>() { @Override protected CompletionStage newCompletionStage() { return ResultSetFutureCallTest.this.future; } @@ -82,7 +82,7 @@ static final class CompletableCallback extends CompletableFuture implement @Test void enqueue_callbackError_onErrorCreatingFuture() { IllegalArgumentException error = new IllegalArgumentException(); - call = new ResultSetFutureCall() { + call = new ResultSetFutureCall<>() { @Override protected CompletionStage newCompletionStage() { throw error; } diff --git a/zipkin-storage/cassandra/src/test/resources/simplelogger.properties b/zipkin-storage/cassandra/src/test/resources/simplelogger.properties index af93d53119e..5bbf1052b94 100644 --- a/zipkin-storage/cassandra/src/test/resources/simplelogger.properties +++ b/zipkin-storage/cassandra/src/test/resources/simplelogger.properties @@ -15,8 +15,8 @@ org.slf4j.simpleLogger.log.com.datastax.oss.driver.internal.core.cql.CqlRequestH org.slf4j.simpleLogger.log.com.datastax.oss.driver.internal.core.control.ControlConnection=error # ignore warnings about too many sessions org.slf4j.simpleLogger.log.com.datastax.oss.driver.internal.core.session.DefaultSession=error -# stop huge spam -org.slf4j.simpleLogger.log.org.testcontainers.dockerclient=off - -# Schema install takes a while. Log basic information to prevent CI from thinking things are hung -org.slf4j.simpleLogger.log.zipkin2.storage.cassandra.CassandraStorageExtension=info +# set to debug to see storage details +org.slf4j.simpleLogger.log.zipkin2=warn +# set to info to see feedback about starting the container +org.slf4j.simpleLogger.log.org.testcontainers=warn +org.slf4j.simpleLogger.log.zipkin2.storage.cassandra.CassandraContainer=info diff --git a/zipkin-storage/elasticsearch/src/test/java/zipkin2/elasticsearch/integration/ElasticsearchExtension.java b/zipkin-storage/elasticsearch/src/test/java/zipkin2/elasticsearch/integration/ElasticsearchExtension.java index 0e0113144fd..3a01f95cdb3 100644 --- a/zipkin-storage/elasticsearch/src/test/java/zipkin2/elasticsearch/integration/ElasticsearchExtension.java +++ b/zipkin-storage/elasticsearch/src/test/java/zipkin2/elasticsearch/integration/ElasticsearchExtension.java @@ -127,7 +127,7 @@ String baseUrl() { // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 static final class ElasticsearchContainer extends GenericContainer { ElasticsearchContainer(int majorVersion) { - super(parse("ghcr.io/openzipkin/zipkin-elasticsearch" + majorVersion + ":3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-elasticsearch" + majorVersion + ":3.0.5")); addExposedPort(9200); waitStrategy = Wait.forHealthcheck(); withLogConsumer(new Slf4jLogConsumer(LOGGER)); diff --git a/zipkin-storage/mysql-v1/src/test/java/zipkin2/storage/mysql/v1/MySQLExtension.java b/zipkin-storage/mysql-v1/src/test/java/zipkin2/storage/mysql/v1/MySQLExtension.java index c08901a9088..ff9fd50c2d2 100644 --- a/zipkin-storage/mysql-v1/src/test/java/zipkin2/storage/mysql/v1/MySQLExtension.java +++ b/zipkin-storage/mysql-v1/src/test/java/zipkin2/storage/mysql/v1/MySQLExtension.java @@ -113,7 +113,7 @@ int port() { // mostly waiting for https://github.com/testcontainers/testcontainers-java/issues/3537 static final class MySQLContainer extends GenericContainer { MySQLContainer() { - super(parse("ghcr.io/openzipkin/zipkin-mysql:3.0.4")); + super(parse("ghcr.io/openzipkin/zipkin-mysql:3.0.5")); addExposedPort(3306); waitStrategy = Wait.forHealthcheck(); withLogConsumer(new Slf4jLogConsumer(LOGGER)); diff --git a/zipkin-storage/pom.xml b/zipkin-storage/pom.xml index 9d94122f228..46a6c1d7a4a 100644 --- a/zipkin-storage/pom.xml +++ b/zipkin-storage/pom.xml @@ -58,6 +58,12 @@ ${project.version} test + + org.slf4j + slf4j-api + ${slf4j.version} + test + org.slf4j slf4j-simple @@ -66,7 +72,7 @@ org.testcontainers - testcontainers + junit-jupiter ${testcontainers.version} test