You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by st...@apache.org on 2023/09/07 12:52:01 UTC
[solr] branch branch_9x updated: SOLR-15367 [9.x] Convert "rid" functionality into a default Tracer (#1868)
This is an automated email from the ASF dual-hosted git repository.
stillalex pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new a940231d05b SOLR-15367 [9.x] Convert "rid" functionality into a default Tracer (#1868)
a940231d05b is described below
commit a940231d05b77a87c22759483af91317b105cb11
Author: Alex D <st...@apache.org>
AuthorDate: Thu Sep 7 05:51:53 2023 -0700
SOLR-15367 [9.x] Convert "rid" functionality into a default Tracer (#1868)
9.x backport and rewrite to work with OpenTracing of https://github.com/apache/solr/pull/1854
---
solr/core/src/java/org/apache/solr/api/Api.java | 2 +-
.../org/apache/solr/core/TracerConfigurator.java | 6 +
.../handler/admin/api/RestoreCollectionAPI.java | 2 +-
.../apache/solr/util/tracing/SimplePropagator.java | 300 +++++++++++++++++++++
.../tracing/BasicAuthIntegrationTracingTest.java | 1 +
.../solr/util/tracing/TestDistributedTracing.java | 1 +
.../TestSimplePropagatorDistributedTracing.java | 118 ++++++++
.../apache/solr/jaeger/TestJaegerConfigurator.java | 1 +
.../opentelemetry/OtelTracerConfiguratorTest.java | 1 +
solr/server/resources/log4j2.xml | 6 +-
.../apache/solr/cloud/MiniSolrCloudCluster.java | 20 ++
11 files changed, 453 insertions(+), 5 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/api/Api.java b/solr/core/src/java/org/apache/solr/api/Api.java
index 54010912ae2..8e881b7f74e 100644
--- a/solr/core/src/java/org/apache/solr/api/Api.java
+++ b/solr/core/src/java/org/apache/solr/api/Api.java
@@ -41,7 +41,7 @@ public abstract class Api implements SpecProvider {
if (commandSchema == null) {
synchronized (this) {
if (commandSchema == null) {
- ValidatingJsonMap commands = getSpec().getMap("commands", null);
+ ValidatingJsonMap commands = spec != null ? getSpec().getMap("commands", null) : null;
commandSchema =
commands != null ? Map.copyOf(ApiBag.getParsedSchema(commands)) : Map.of();
}
diff --git a/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java b/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
index ba36ed127ec..c7259e0b7be 100644
--- a/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
+++ b/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
@@ -25,6 +25,7 @@ import java.lang.invoke.MethodHandles;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
+import org.apache.solr.util.tracing.SimplePropagator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +33,9 @@ import org.slf4j.LoggerFactory;
public abstract class TracerConfigurator implements NamedListInitializedPlugin {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ public static final boolean TRACE_ID_GEN_ENABLED =
+ Boolean.parseBoolean(System.getProperty("solr.alwaysOnTraceId", "true"));
+
public abstract Tracer getTracer();
public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
@@ -48,6 +52,8 @@ public abstract class TracerConfigurator implements NamedListInitializedPlugin {
configurator.init(info.initArgs);
return configurator.getTracer();
});
+ } else if (TRACE_ID_GEN_ENABLED) {
+ SimplePropagator.load();
}
if (GlobalTracer.isRegistered()) {
// ideally we would furthermore check that it's not a no-op impl either but
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCollectionAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCollectionAPI.java
index 18caed1933a..1809d83f6b9 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCollectionAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCollectionAPI.java
@@ -108,8 +108,8 @@ public class RestoreCollectionAPI extends BackupAPIBase {
}
final String collectionName = requestBody.collection;
- recordCollectionForLogAndTracing(collectionName, solrQueryRequest);
SolrIdentifierValidator.validateCollectionName(collectionName);
+ recordCollectionForLogAndTracing(collectionName, solrQueryRequest);
if (coreContainer.getAliases().hasAlias(collectionName)) {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
diff --git a/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java b/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java
new file mode 100644
index 00000000000..f2141f5aa63
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.util.tracing;
+
+import io.opentracing.Scope;
+import io.opentracing.ScopeManager;
+import io.opentracing.Span;
+import io.opentracing.SpanContext;
+import io.opentracing.Tracer;
+import io.opentracing.Tracer.SpanBuilder;
+import io.opentracing.noop.NoopSpan;
+import io.opentracing.propagation.Format;
+import io.opentracing.propagation.TextMap;
+import io.opentracing.tag.Tag;
+import io.opentracing.util.GlobalTracer;
+import io.opentracing.util.ThreadLocalScopeManager;
+import java.lang.invoke.MethodHandles;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicLong;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SimplePropagator {
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private static final String TRACE_HOST_NAME =
+ System.getProperty("trace_host_name", System.getProperty("host"));
+
+ static final String TRACE_ID = System.getProperty("TRACE_ID", "X-Trace-Id");
+
+ private static final AtomicLong traceCounter = new AtomicLong(0);
+
+ public static void load() {
+ GlobalTracer.registerIfAbsent(
+ () -> {
+ log.info("Always-on trace id generation enabled.");
+ return new SimplePropagatorTracer();
+ });
+ }
+
+ private static String newTraceId() {
+ return TRACE_HOST_NAME + "-" + traceCounter.incrementAndGet();
+ }
+
+ /**
+ * Tracer that only aims to do simple header propagation, tailored to how Solr works.
+ *
+ * <p>Heavily inspired from JaegerTracer, NoopTracer
+ */
+ static class SimplePropagatorTracer implements Tracer {
+
+ private final ScopeManager scopeManager = new ThreadLocalScopeManager();
+
+ @Override
+ public ScopeManager scopeManager() {
+ return scopeManager;
+ }
+
+ @Override
+ public Span activeSpan() {
+ return scopeManager.activeSpan();
+ }
+
+ @Override
+ public Scope activateSpan(Span span) {
+ return scopeManager.activate(span);
+ }
+
+ @Override
+ public SpanBuilder buildSpan(String operationName) {
+ return new SimplePropagatorSpanBuilder(scopeManager);
+ }
+
+ @Override
+ public void close() {}
+
+ @Override
+ public <C> void inject(SpanContext spanContext, Format<C> format, C carrier) {
+ if (!format.equals(Format.Builtin.HTTP_HEADERS)) {
+ // unsupported via the Solr injectors
+ return;
+ }
+ String traceId = spanContext.toTraceId();
+ if (traceId != null && !traceId.isEmpty()) {
+ TextMap tm = (TextMap) carrier;
+ tm.put(TRACE_ID, traceId);
+ }
+ }
+
+ @Override
+ public <C> SpanContext extract(Format<C> format, C carrier) {
+ if (!format.equals(Format.Builtin.HTTP_HEADERS)) {
+ // unsupported via the Solr injectors
+ return NoopSpan.INSTANCE.context();
+ }
+
+ String traceId = null;
+ TextMap tm = (TextMap) carrier;
+ Iterator<Entry<String, String>> it = tm.iterator();
+ while (it.hasNext()) {
+ var e = it.next();
+ // 'equalsIgnoreCase' because header name might be lowercase
+ if (e.getKey().equalsIgnoreCase(TRACE_ID)) {
+ traceId = e.getValue();
+ break;
+ }
+ }
+ if (traceId == null) {
+ traceId = newTraceId();
+ }
+ return new SimplePropagatorSpan(traceId);
+ }
+
+ @Override
+ public String toString() {
+ return "SimplePropagator";
+ }
+ }
+
+ private static final class SimplePropagatorSpanBuilder implements SpanBuilder {
+
+ private final ScopeManager scopeManager;
+ // storing parent to support the parent being injected via the asChildOf method
+ private SpanContext parent;
+
+ public SimplePropagatorSpanBuilder(ScopeManager scopeManager) {
+ this.scopeManager = scopeManager;
+ }
+
+ @Override
+ public Span start() {
+ if (parent != null) {
+ if (parent instanceof SimplePropagatorSpan) {
+ return (SimplePropagatorSpan) parent;
+ } else {
+ return NoopSpan.INSTANCE;
+ }
+ }
+ var activeSpan = scopeManager.activeSpan();
+ if (activeSpan != null) {
+ return activeSpan;
+ } else {
+ return new SimplePropagatorSpan(newTraceId());
+ }
+ }
+
+ @Override
+ public SpanBuilder addReference(String referenceType, SpanContext reference) {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder asChildOf(SpanContext parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ @Override
+ public SpanBuilder asChildOf(Span parent) {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder ignoreActiveSpan() {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder withStartTimestamp(long arg0) {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder withTag(String arg0, String arg1) {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder withTag(String arg0, boolean arg1) {
+ return this;
+ }
+
+ @Override
+ public SpanBuilder withTag(String arg0, Number arg1) {
+ return this;
+ }
+
+ @Override
+ public <T> SpanBuilder withTag(Tag<T> arg0, T arg1) {
+ return this;
+ }
+ }
+
+ private static final class SimplePropagatorSpan implements Span, SpanContext, NoopSpan {
+
+ private final String traceId;
+
+ private SimplePropagatorSpan(String traceId) {
+ this.traceId = traceId;
+ }
+
+ @Override
+ public String toTraceId() {
+ return traceId;
+ }
+
+ @Override
+ public String toSpanId() {
+ return "";
+ }
+
+ @Override
+ public Iterable<Map.Entry<String, String>> baggageItems() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public SpanContext context() {
+ return this;
+ }
+
+ @Override
+ public void finish() {}
+
+ @Override
+ public void finish(long arg0) {}
+
+ @Override
+ public String getBaggageItem(String arg0) {
+ return null;
+ }
+
+ @Override
+ public Span log(Map<String, ?> arg0) {
+ return this;
+ }
+
+ @Override
+ public Span log(String arg0) {
+ return this;
+ }
+
+ @Override
+ public Span log(long arg0, Map<String, ?> arg1) {
+ return this;
+ }
+
+ @Override
+ public Span log(long arg0, String arg1) {
+ return this;
+ }
+
+ @Override
+ public Span setBaggageItem(String arg0, String arg1) {
+ return this;
+ }
+
+ @Override
+ public Span setOperationName(String arg0) {
+ return this;
+ }
+
+ @Override
+ public Span setTag(String arg0, String arg1) {
+ return this;
+ }
+
+ @Override
+ public Span setTag(String arg0, boolean arg1) {
+ return this;
+ }
+
+ @Override
+ public Span setTag(String arg0, Number arg1) {
+ return this;
+ }
+
+ @Override
+ public <T> Span setTag(Tag<T> arg0, T arg1) {
+ return this;
+ }
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/util/tracing/BasicAuthIntegrationTracingTest.java b/solr/core/src/test/org/apache/solr/util/tracing/BasicAuthIntegrationTracingTest.java
index 2313cd808d7..0fd7a7cf77b 100644
--- a/solr/core/src/test/org/apache/solr/util/tracing/BasicAuthIntegrationTracingTest.java
+++ b/solr/core/src/test/org/apache/solr/util/tracing/BasicAuthIntegrationTracingTest.java
@@ -77,6 +77,7 @@ public class BasicAuthIntegrationTracingTest extends SolrCloudTestCase {
.addConfig(
"config", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
.withSecurityJson(SECURITY_JSON)
+ .withTraceIdGenerationDisabled()
.configure();
CollectionAdminRequest.createCollection(COLLECTION, "config", 2, 2)
.setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE)
diff --git a/solr/core/src/test/org/apache/solr/util/tracing/TestDistributedTracing.java b/solr/core/src/test/org/apache/solr/util/tracing/TestDistributedTracing.java
index b28f15e18bd..8fe52fa515f 100644
--- a/solr/core/src/test/org/apache/solr/util/tracing/TestDistributedTracing.java
+++ b/solr/core/src/test/org/apache/solr/util/tracing/TestDistributedTracing.java
@@ -55,6 +55,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
configureCluster(4)
.addConfig(
"config", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+ .withTraceIdGenerationDisabled()
.configure();
CollectionAdminRequest.createCollection(COLLECTION, "config", 2, 2)
.setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE)
diff --git a/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java b/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java
new file mode 100644
index 00000000000..a08d3ade5b1
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.util.tracing;
+
+import io.opentracing.util.GlobalTracer;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.util.SuppressForbidden;
+import org.apache.solr.common.util.TimeSource;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.logging.MDCLoggingContext;
+import org.apache.solr.update.processor.LogUpdateProcessorFactory;
+import org.apache.solr.util.LogListener;
+import org.apache.solr.util.TimeOut;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+@SuppressForbidden(reason = "We need to use log4J2 classes directly to test MDC impacts")
+public class TestSimplePropagatorDistributedTracing extends SolrCloudTestCase {
+
+ private static final String COLLECTION = "collection1";
+
+ @BeforeClass
+ public static void setupCluster() throws Exception {
+
+ configureCluster(4).addConfig("conf", configset("cloud-minimal")).configure();
+
+ TimeOut timeOut = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME);
+ timeOut.waitFor(
+ "Waiting for GlobalTracer is registered",
+ () -> GlobalTracer.get().toString().contains("SimplePropagator"));
+
+ CollectionAdminRequest.createCollection(COLLECTION, "conf", 2, 2)
+ .process(cluster.getSolrClient());
+ cluster.waitForActiveCollection(COLLECTION, 2, 4);
+ }
+
+ @Test
+ public void test() throws IOException, SolrServerException {
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+
+ // Indexing has trace ids
+ try (LogListener reqLog = LogListener.info(LogUpdateProcessorFactory.class.getName())) {
+ // verify all indexing events have trace id present
+ cloudClient.add(COLLECTION, sdoc("id", "1"));
+ cloudClient.add(COLLECTION, sdoc("id", "2"));
+ cloudClient.add(COLLECTION, sdoc("id", "3"));
+ var queue = reqLog.getQueue();
+ assertFalse(queue.isEmpty());
+ while (!queue.isEmpty()) {
+ var reqEvent = queue.poll();
+ String evTraceId = reqEvent.getContextData().getValue(MDCLoggingContext.TRACE_ID);
+ assertNotNull(evTraceId);
+ }
+
+ // TODO this doesn't work due to solr client creating the UpdateRequest without headers
+ // // verify all events have the same 'custom' traceid
+ // String traceId = "tidTestSimplePropagatorDistributedTracing0";
+ // var doc = sdoc("id", "4");
+ // UpdateRequest u = new UpdateRequest();
+ // u.add(doc);
+ // u.addHeader(SimplePropagator.TRACE_ID, traceId);
+ // var r1 = u.process(cloudClient, COLLECTION);
+ // assertEquals(0, r1.getStatus());
+ // assertSameTraceId(reqLog, traceId);
+ }
+
+ // Searching has trace ids
+ try (LogListener reqLog = LogListener.info(SolrCore.class.getName() + ".Request")) {
+ // verify all query events have the same auto-generated traceid
+ var r1 = cloudClient.query(COLLECTION, new SolrQuery("*:*"));
+ assertEquals(0, r1.getStatus());
+ assertSameTraceId(reqLog, null);
+
+ // verify all query events have the same 'custom' traceid
+ String traceId = "tidTestSimplePropagatorDistributedTracing1";
+ var q = new QueryRequest(new SolrQuery("*:*"));
+ q.addHeader(SimplePropagator.TRACE_ID, traceId);
+ var r2 = q.process(cloudClient, COLLECTION);
+ assertEquals(0, r2.getStatus());
+ assertSameTraceId(reqLog, traceId);
+ }
+ }
+
+ private void assertSameTraceId(LogListener reqLog, String traceId) {
+ var queue = reqLog.getQueue();
+ assertFalse(queue.isEmpty());
+ if (traceId == null) {
+ traceId = queue.poll().getContextData().getValue(MDCLoggingContext.TRACE_ID);
+ assertNotNull(traceId);
+ }
+ while (!queue.isEmpty()) {
+ var reqEvent = queue.poll();
+ String evTraceId = reqEvent.getContextData().getValue(MDCLoggingContext.TRACE_ID);
+ assertEquals(traceId, evTraceId);
+ }
+ }
+}
diff --git a/solr/modules/jaegertracer-configurator/src/test/org/apache/solr/jaeger/TestJaegerConfigurator.java b/solr/modules/jaegertracer-configurator/src/test/org/apache/solr/jaeger/TestJaegerConfigurator.java
index 4759c5ced19..0291b46ff0b 100644
--- a/solr/modules/jaegertracer-configurator/src/test/org/apache/solr/jaeger/TestJaegerConfigurator.java
+++ b/solr/modules/jaegertracer-configurator/src/test/org/apache/solr/jaeger/TestJaegerConfigurator.java
@@ -49,6 +49,7 @@ public class TestJaegerConfigurator extends SolrTestCaseJ4 {
new MiniSolrCloudCluster.Builder(2, createTempDir())
.addConfig("config", TEST_PATH().resolve("collection1").resolve("conf"))
.withSolrXml(getFile("solr/solr.xml").toPath())
+ .withTraceIdGenerationDisabled()
.build();
try {
TimeOut timeOut = new TimeOut(2, TimeUnit.MINUTES, TimeSource.NANO_TIME);
diff --git a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
index 5aef12103da..c7cda9fbb7a 100644
--- a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
+++ b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
@@ -103,6 +103,7 @@ public class OtelTracerConfiguratorTest extends SolrTestCaseJ4 {
new MiniSolrCloudCluster.Builder(2, createTempDir())
.addConfig("config", TEST_PATH().resolve("collection1").resolve("conf"))
.withSolrXml(getFile("solr/solr.xml").toPath())
+ .withTraceIdGenerationDisabled()
.build();
try {
assertTrue(
diff --git a/solr/server/resources/log4j2.xml b/solr/server/resources/log4j2.xml
index 186e86bd8cc..006de0c965c 100644
--- a/solr/server/resources/log4j2.xml
+++ b/solr/server/resources/log4j2.xml
@@ -23,7 +23,7 @@
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>
- %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
+ %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}%notEmpty{ t:%X{trace_id}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
</Pattern>
</PatternLayout>
</Console>
@@ -34,7 +34,7 @@
filePattern="${sys:solr.log.dir}/solr.log.%i" >
<PatternLayout>
<Pattern>
- %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
+ %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}%notEmpty{ t:%X{trace_id}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
</Pattern>
</PatternLayout>
<Policies>
@@ -50,7 +50,7 @@
filePattern="${sys:solr.log.dir}/solr_slow_requests.log.%i" >
<PatternLayout>
<Pattern>
- %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
+ %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%notEmpty{c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{ x:%X{core}}%notEmpty{ t:%X{trace_id}}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n
</Pattern>
</PatternLayout>
<Policies>
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
index 704cbfa8589..6ebd4400ecf 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
@@ -78,9 +78,11 @@ import org.apache.solr.common.util.IOUtils;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.TracerConfigurator;
import org.apache.solr.embedded.JettyConfig;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.TimeOut;
+import org.apache.solr.util.tracing.SimplePropagator;
import org.apache.zookeeper.KeeperException;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.servlet.ServletHolder;
@@ -1106,6 +1108,7 @@ public class MiniSolrCloudCluster {
private boolean useDistributedCollectionConfigSetExecution;
private boolean useDistributedClusterStateUpdate;
private boolean formatZkServer = true;
+ private boolean disableTraceIdGeneration = false;
/**
* Create a builder
@@ -1299,6 +1302,11 @@ public class MiniSolrCloudCluster {
"solr.distributedClusterStateUpdates",
Boolean.toString(useDistributedClusterStateUpdate));
+ // eager init to prevent OTEL init races caused by test setup
+ if (!disableTraceIdGeneration && TracerConfigurator.TRACE_ID_GEN_ENABLED) {
+ SimplePropagator.load();
+ }
+
JettyConfig jettyConfig = jettyConfigBuilder.build();
MiniSolrCloudCluster cluster =
new MiniSolrCloudCluster(
@@ -1341,5 +1349,17 @@ public class MiniSolrCloudCluster {
cluster.put(key, value);
return this;
}
+
+ /**
+ * Disables the default/built-in simple trace ID generation/propagation.
+ *
+ * <p>Tracers are registered as global singletons and if for example a test needs to use a
+ * MockTracer or a "real" Tracer, it needs to call this method so that the test setup doesn't
+ * accidentally reset the Tracer it wants to use.
+ */
+ public Builder withTraceIdGenerationDisabled() {
+ this.disableTraceIdGeneration = true;
+ return this;
+ }
}
}