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/14 23:18:24 UTC
[solr] branch branch_9x updated: SOLR-16938 Auto configure tracer without a tag in solr.xml
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 ff385d7b63c SOLR-16938 Auto configure tracer without a <tracerConfig> tag in solr.xml
ff385d7b63c is described below
commit ff385d7b63c913b9724876b359cae5c63455f13e
Author: Alex Deparvu <st...@apache.org>
AuthorDate: Thu Sep 14 16:17:03 2023 -0700
SOLR-16938 Auto configure tracer without a <tracerConfig> tag in solr.xml
(manual cherry picked from commit 5f25f09de4652c1c48095e45f68c2f0e28f8a464)
---
solr/CHANGES.txt | 2 +
.../org/apache/solr/core/TracerConfigurator.java | 64 ++++++++++++++++++++++
.../apache/solr/core/TestTracerConfigurator.java | 63 +++++++++++++++++++++
solr/modules/opentelemetry/build.gradle | 1 +
.../solr/opentelemetry/OtelTracerConfigurator.java | 37 ++++++++-----
.../opentelemetry/OtelTracerConfiguratorTest.java | 10 +++-
.../pages/distributed-tracing.adoc | 2 +
7 files changed, 162 insertions(+), 17 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 21055518960..3e200832508 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -68,6 +68,8 @@ Improvements
* SOLR-16461: `/solr/coreName/replication?command=backup` now has a v2 equivalent, available at
`/api/cores/coreName/replication/backups` (Sanjay Dutt, Jason Gerlowski, Alex Deparvu)
+* SOLR-16938: Auto configure tracer without a <tracerConfig> tag in solr.xml (Alex Deparvu)
+
Optimizations
---------------------
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 c7259e0b7be..30ce2071465 100644
--- a/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
+++ b/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
@@ -22,8 +22,12 @@ import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import java.lang.invoke.MethodHandles;
+import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.NamedList;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.tracing.SimplePropagator;
import org.slf4j.Logger;
@@ -36,6 +40,10 @@ public abstract class TracerConfigurator implements NamedListInitializedPlugin {
public static final boolean TRACE_ID_GEN_ENABLED =
Boolean.parseBoolean(System.getProperty("solr.alwaysOnTraceId", "true"));
+ private static final String DEFAULT_CLASS_NAME =
+ System.getProperty(
+ "solr.otelDefaultConfigurator", "org.apache.solr.opentelemetry.OtelTracerConfigurator");
+
public abstract Tracer getTracer();
public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
@@ -52,6 +60,8 @@ public abstract class TracerConfigurator implements NamedListInitializedPlugin {
configurator.init(info.initArgs);
return configurator.getTracer();
});
+ } else if (shouldAutoConfigOTEL()) {
+ GlobalTracer.registerIfAbsent(() -> autoConfigOTEL(loader));
} else if (TRACE_ID_GEN_ENABLED) {
SimplePropagator.load();
}
@@ -102,4 +112,58 @@ public abstract class TracerConfigurator implements NamedListInitializedPlugin {
}
}
}
+
+ private static Tracer autoConfigOTEL(SolrResourceLoader loader) {
+ try {
+ TracerConfigurator configurator =
+ loader.newInstance(DEFAULT_CLASS_NAME, TracerConfigurator.class);
+ configurator.init(new NamedList<>());
+ return configurator.getTracer();
+ } catch (SolrException e) {
+ log.error(
+ "Unable to auto-config OpenTelemetry with class {}. Make sure you have enabled the 'opentelemetry' module",
+ DEFAULT_CLASS_NAME,
+ e);
+ }
+ return GlobalTracer.get();
+ }
+
+ /**
+ * Best effort way to determine if we should attempt to init OTEL from system properties.
+ *
+ * @return true if OTEL should be init
+ */
+ static boolean shouldAutoConfigOTEL() {
+ var env = System.getenv();
+ boolean isSdkDisabled = Boolean.parseBoolean(getConfig("OTEL_SDK_DISABLED", env));
+ if (isSdkDisabled) {
+ return false;
+ }
+ return getConfig("OTEL_SERVICE_NAME", env) != null;
+ }
+
+ /**
+ * Returns system property if found, else returns environment variable, or null if none found.
+ *
+ * @param envName the environment variable to look for
+ * @param env current env
+ * @return the resolved value
+ */
+ protected static String getConfig(String envName, Map<String, String> env) {
+ String sysName = envNameToSyspropName(envName);
+ String sysValue = System.getProperty(sysName);
+ String envValue = env.get(envName);
+ return sysValue != null ? sysValue : envValue;
+ }
+
+ /**
+ * In OTEL Java SDK there is a convention that the java property name for OTEL_FOO_BAR is
+ * otel.foo.bar
+ *
+ * @param envName the environmnet name to convert
+ * @return the corresponding sysprop name
+ */
+ protected static String envNameToSyspropName(String envName) {
+ return envName.toLowerCase(Locale.ROOT).replace("_", ".");
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/core/TestTracerConfigurator.java b/solr/core/src/test/org/apache/solr/core/TestTracerConfigurator.java
new file mode 100644
index 00000000000..a0bec839e91
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/core/TestTracerConfigurator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core;
+
+import io.opentracing.util.GlobalTracer;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.util.ExecutorUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestTracerConfigurator extends SolrTestCaseJ4 {
+
+ @BeforeClass
+ public static void setUpProperties() throws Exception {
+ System.setProperty("otel.service.name", "something");
+ System.setProperty("solr.otelDefaultConfigurator", "configuratorClassDoesNotExistTest");
+ }
+
+ @AfterClass
+ public static void clearProperties() throws Exception {
+ System.clearProperty("solr.otelDefaultConfigurator");
+ System.clearProperty("otel.service.name");
+ }
+
+ @Test
+ public void configuratorClassDoesNotExistTest() {
+ // to be safe because this test tests tracing.
+ resetGlobalTracer();
+ ExecutorUtil.resetThreadLocalProviders();
+ assertTrue(TracerConfigurator.shouldAutoConfigOTEL());
+ SolrResourceLoader loader = new SolrResourceLoader(TEST_PATH().resolve("collection1"));
+ TracerConfigurator.loadTracer(loader, null);
+
+ assertTrue(
+ "Expecting noop otel after failure to auto-init",
+ GlobalTracer.get().toString().contains("GlobalTracer"));
+ }
+
+ @Test
+ public void otelDisabledByProperty() {
+ System.setProperty("otel.sdk.disabled", "true");
+ try {
+ assertFalse(TracerConfigurator.shouldAutoConfigOTEL());
+ } finally {
+ System.clearProperty("otel.sdk.disabled");
+ }
+ }
+}
diff --git a/solr/modules/opentelemetry/build.gradle b/solr/modules/opentelemetry/build.gradle
index 225068b48e9..78119966758 100644
--- a/solr/modules/opentelemetry/build.gradle
+++ b/solr/modules/opentelemetry/build.gradle
@@ -21,6 +21,7 @@ description = 'Open Telemetry (OTEL) tracer'
dependencies {
implementation project(':solr:core')
+ implementation project(':solr:solrj')
implementation platform('io.opentelemetry:opentelemetry-bom')
diff --git a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
index 6b876c7c1b6..d892ee20f7e 100644
--- a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
+++ b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
@@ -27,6 +27,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.TracerConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,6 +42,11 @@ public class OtelTracerConfigurator extends TracerConfigurator {
// Copy of environment. Can be overridden by tests
Map<String, String> currentEnv = System.getenv();
+ @Override
+ public void init(NamedList<?> args) {
+ injectPluginSettingsIfNotConfigured(args);
+ }
+
@Override
public Tracer getTracer() {
setDefaultIfNotConfigured("OTEL_SERVICE_NAME", "solr");
@@ -68,6 +74,20 @@ public class OtelTracerConfigurator extends TracerConfigurator {
return new ClosableTracerShim(shim, otelSdk.getSdkTracerProvider());
}
+ /**
+ * Will inject plugin configuration values into system properties if not already setup (existing
+ * system properties take precedence)
+ */
+ private void injectPluginSettingsIfNotConfigured(NamedList<?> args) {
+ args.forEach(
+ (k, v) -> {
+ var asSysName = envNameToSyspropName(k);
+ if (asSysName.startsWith("otel.")) {
+ setDefaultIfNotConfigured(asSysName, v.toString());
+ }
+ });
+ }
+
/**
* Add explicit tags statically to all traces, independent of request. Attributes with same name
* supplied in ENV or SysProp will take precedence over attributes added in code.
@@ -124,24 +144,11 @@ public class OtelTracerConfigurator extends TracerConfigurator {
/**
* Returns system property if found, else returns environment variable, or null if none found.
*
- * @param envName the environment to look for
+ * @param envName the environment variable to look for
* @return the resolved value
*/
String getEnvOrSysprop(String envName) {
- String envValue = currentEnv.get(envName);
- String propValue = System.getProperty(envNameToSyspropName(envName));
- return propValue != null ? propValue : envValue;
- }
-
- /**
- * In OTEL Java SDK there is a convention that the java property name for OTEL_FOO_BAR is
- * otel.foo.bar
- *
- * @param envName the environmnet name to convert
- * @return the corresponding sysprop name
- */
- static String envNameToSyspropName(String envName) {
- return envName.toLowerCase(Locale.ROOT).replace("_", ".");
+ return getConfig(envName, currentEnv);
}
/**
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 c7cda9fbb7a..df2692f1066 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
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.cloud.MiniSolrCloudCluster;
import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.NamedList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +45,10 @@ public class OtelTracerConfiguratorTest extends SolrTestCaseJ4 {
System.setProperty("otelnothere", "bar");
System.setProperty("otel.k1", "prop-k1");
System.setProperty("otel.k3", "prop-k3");
+ NamedList<String> conf = new NamedList<>();
+ conf.add("OTEL_K1", "conf-k1");
+ conf.add("otel.k7", "conf-k7");
+ instance.init(conf);
// to be safe because this test tests tracing.
resetGlobalTracer();
@@ -66,14 +71,15 @@ public class OtelTracerConfiguratorTest extends SolrTestCaseJ4 {
Map.of(
"OTEL_K1", "prop-k1",
"OTEL_K2", "env-k2",
- "OTEL_K3", "prop-k3");
+ "OTEL_K3", "prop-k3",
+ "OTEL_K7", "conf-k7");
assertEquals(expected, instance.getCurrentOtelConfig());
}
@Test
public void testGetCurrentOtelConfigAsString() {
assertEquals(
- "OTEL_K1=prop-k1; OTEL_K2=env-k2; OTEL_K3=prop-k3",
+ "OTEL_K1=prop-k1; OTEL_K2=env-k2; OTEL_K3=prop-k3; OTEL_K7=conf-k7",
instance.getCurrentOtelConfigAsString());
}
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
index fcd336c84f4..aea35725464 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
@@ -64,6 +64,8 @@ This module brings support for the industry standard https://opentelemetry.io[Op
<tracerConfig name="tracerConfig" class="org.apache.solr.opentelemetry.OtelTracerConfigurator"/>
----
+As an alternative to changing the `solr.xml` file, the `OTEL` tracer will be enabled if the system property `otel.service.name` or environment variable `OTEL_SERVICE_NAME` is present. The `opentelemetry` module still needs to be enabled for the tracer to work.
+
Enable the module with either system property `-Dsolr.modules=opentelemetry` or environment variable `SOLR_MODULES=opentelemetry`.
=== Configuration