dsmiley commented on code in PR #2687:
URL: https://github.com/apache/solr/pull/2687#discussion_r1740338583


##########
solr/core/src/java/org/apache/solr/core/TracerConfigurator.java:
##########
@@ -38,33 +41,53 @@
 public abstract class TracerConfigurator implements NamedListInitializedPlugin 
{
 
   public static final boolean TRACE_ID_GEN_ENABLED =
-      Boolean.parseBoolean(EnvUtils.getProperty("solr.alwaysOnTraceId", 
"true"));
+      EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId", true);
 
   private static final String DEFAULT_CLASS_NAME =
       EnvUtils.getProperty(
           "solr.otelDefaultConfigurator", 
"org.apache.solr.opentelemetry.OtelTracerConfigurator");
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
-    if (info != null && info.isEnabled()) {
-      TracerConfigurator configurator =
-          loader.newInstance(info.className, TracerConfigurator.class);
-      configurator.init(info.initArgs);
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return configurator.getTracer();
-    }
-    if (shouldAutoConfigOTEL()) {
-      return autoConfigOTEL(loader);
+  /** Initializes {@link io.opentelemetry.api.GlobalOpenTelemetry} and returns 
a Tracer. */
+  public static synchronized Tracer loadTracer(SolrResourceLoader loader, 
PluginInfo info) {
+    // synchronized to avoid races in tests starting Solr concurrently setting 
GlobalOpenTelemetry
+    if (TraceUtils.OTEL_AGENT_PRESENT) {
+      log.info("OpenTelemetry Java agent was already installed; skipping OTEL 
initialization");
+    } else {
+      OpenTelemetry otel = null;
+      if (info != null && info.isEnabled()) {
+        var configurator = loader.newInstance(info.className, 
TracerConfigurator.class);
+        configurator.init(info.initArgs);
+        otel = configurator.createOtel();
+      } else if (shouldAutoConfigOTEL()) {
+        otel = autoConfigOTEL(loader); // could return null if failed to load
+        if (otel != null) {
+          log.info("OpenTelemetry loaded via auto configuration.");
+        }
+      }
+      if (otel == null && TRACE_ID_GEN_ENABLED) {
+        otel = 
OpenTelemetry.propagating(ContextPropagators.create(SimplePropagator.getInstance()));
+        log.info("OpenTelemetry loaded with simple propagation only.");
+      }
+      if (otel == null) {
+        otel = OpenTelemetry.noop();
+      }
+
+      try {
+        GlobalOpenTelemetry.set(otel); // throws IllegalStateException if 
already set

Review Comment:
   this is the one spot where we call this.  Previously it was in multiple 
places which was confusing and hard to reason about.



##########
solr/core/src/java/org/apache/solr/core/TracerConfigurator.java:
##########
@@ -38,33 +41,53 @@
 public abstract class TracerConfigurator implements NamedListInitializedPlugin 
{
 
   public static final boolean TRACE_ID_GEN_ENABLED =
-      Boolean.parseBoolean(EnvUtils.getProperty("solr.alwaysOnTraceId", 
"true"));
+      EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId", true);
 
   private static final String DEFAULT_CLASS_NAME =
       EnvUtils.getProperty(
           "solr.otelDefaultConfigurator", 
"org.apache.solr.opentelemetry.OtelTracerConfigurator");
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
-    if (info != null && info.isEnabled()) {
-      TracerConfigurator configurator =
-          loader.newInstance(info.className, TracerConfigurator.class);
-      configurator.init(info.initArgs);
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return configurator.getTracer();
-    }
-    if (shouldAutoConfigOTEL()) {
-      return autoConfigOTEL(loader);
+  /** Initializes {@link io.opentelemetry.api.GlobalOpenTelemetry} and returns 
a Tracer. */
+  public static synchronized Tracer loadTracer(SolrResourceLoader loader, 
PluginInfo info) {
+    // synchronized to avoid races in tests starting Solr concurrently setting 
GlobalOpenTelemetry
+    if (TraceUtils.OTEL_AGENT_PRESENT) {
+      log.info("OpenTelemetry Java agent was already installed; skipping OTEL 
initialization");
+    } else {
+      OpenTelemetry otel = null;
+      if (info != null && info.isEnabled()) {
+        var configurator = loader.newInstance(info.className, 
TracerConfigurator.class);
+        configurator.init(info.initArgs);
+        otel = configurator.createOtel();
+      } else if (shouldAutoConfigOTEL()) {
+        otel = autoConfigOTEL(loader); // could return null if failed to load
+        if (otel != null) {
+          log.info("OpenTelemetry loaded via auto configuration.");
+        }
+      }
+      if (otel == null && TRACE_ID_GEN_ENABLED) {
+        otel = 
OpenTelemetry.propagating(ContextPropagators.create(SimplePropagator.getInstance()));
+        log.info("OpenTelemetry loaded with simple propagation only.");
+      }
+      if (otel == null) {
+        otel = OpenTelemetry.noop();
+      }
+
+      try {
+        GlobalOpenTelemetry.set(otel); // throws IllegalStateException if 
already set
+        // skips needless ExecutorUtil.addThreadLocalProvider below
+        if (otel == OpenTelemetry.noop()) return otel.getTracer("solr");
+      } catch (IllegalStateException e) {
+        log.info("GlobalOpenTelemetry was already initialized (a Java agent?); 
using that");

Review Comment:
   Note that its common tests will log "OpenTelemetry loaded with simple 
propagation only." but then log immediately after "GlobalOpenTelemetry was 
already initialized (a Java agent?); using that" if the test uses more than one 
CoreContainer (Solr node).  I so wish GlobalOpenTelemetry had a way to know if 
it's been set already.



##########
solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/BasicAuthIntegrationTracingTest.java:
##########
@@ -31,23 +33,23 @@
 import org.apache.solr.security.BasicAuthPlugin;
 import org.apache.solr.util.SecurityJson;
 import org.apache.solr.util.tracing.TraceUtils;
-import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
 
 public class BasicAuthIntegrationTracingTest extends SolrCloudTestCase {
 
   private static final String COLLECTION = "collection1";
 
+  @ClassRule public static OpenTelemetryRule otelRule = 
OpenTelemetryRule.create();

Review Comment:
   I was about to write an equivalent of OpenTelemetryRule when I found that it 
already exists :-)
   
   FYI note it has docs that it doesn't work in a ClassRule yet I see it works 
here.



##########
solr/core/src/java/org/apache/solr/core/TracerConfigurator.java:
##########
@@ -38,33 +41,53 @@
 public abstract class TracerConfigurator implements NamedListInitializedPlugin 
{
 
   public static final boolean TRACE_ID_GEN_ENABLED =
-      Boolean.parseBoolean(EnvUtils.getProperty("solr.alwaysOnTraceId", 
"true"));
+      EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId", true);
 
   private static final String DEFAULT_CLASS_NAME =
       EnvUtils.getProperty(
           "solr.otelDefaultConfigurator", 
"org.apache.solr.opentelemetry.OtelTracerConfigurator");
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
-    if (info != null && info.isEnabled()) {
-      TracerConfigurator configurator =
-          loader.newInstance(info.className, TracerConfigurator.class);
-      configurator.init(info.initArgs);
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return configurator.getTracer();
-    }
-    if (shouldAutoConfigOTEL()) {
-      return autoConfigOTEL(loader);
+  /** Initializes {@link io.opentelemetry.api.GlobalOpenTelemetry} and returns 
a Tracer. */
+  public static synchronized Tracer loadTracer(SolrResourceLoader loader, 
PluginInfo info) {
+    // synchronized to avoid races in tests starting Solr concurrently setting 
GlobalOpenTelemetry
+    if (TraceUtils.OTEL_AGENT_PRESENT) {
+      log.info("OpenTelemetry Java agent was already installed; skipping OTEL 
initialization");
+    } else {
+      OpenTelemetry otel = null;
+      if (info != null && info.isEnabled()) {
+        var configurator = loader.newInstance(info.className, 
TracerConfigurator.class);
+        configurator.init(info.initArgs);
+        otel = configurator.createOtel();
+      } else if (shouldAutoConfigOTEL()) {
+        otel = autoConfigOTEL(loader); // could return null if failed to load
+        if (otel != null) {
+          log.info("OpenTelemetry loaded via auto configuration.");
+        }
+      }
+      if (otel == null && TRACE_ID_GEN_ENABLED) {
+        otel = 
OpenTelemetry.propagating(ContextPropagators.create(SimplePropagator.getInstance()));
+        log.info("OpenTelemetry loaded with simple propagation only.");
+      }
+      if (otel == null) {
+        otel = OpenTelemetry.noop();
+      }
+
+      try {
+        GlobalOpenTelemetry.set(otel); // throws IllegalStateException if 
already set
+        // skips needless ExecutorUtil.addThreadLocalProvider below
+        if (otel == OpenTelemetry.noop()) return otel.getTracer("solr");
+      } catch (IllegalStateException e) {
+        log.info("GlobalOpenTelemetry was already initialized (a Java agent?); 
using that");
+      }
     }
-    if (TRACE_ID_GEN_ENABLED) {
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return SimplePropagator.load();
-    }
-    return TraceUtils.getGlobalTracer();
+
+    ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
+    return TraceUtils.getGlobalTracer(); // GlobalOpenTelemetry.get...
   }
 
-  protected abstract Tracer getTracer();
+  protected abstract OpenTelemetry createOtel();

Review Comment:
   this is the API change



##########
solr/core/src/java/org/apache/solr/core/TracerConfigurator.java:
##########
@@ -38,33 +41,53 @@
 public abstract class TracerConfigurator implements NamedListInitializedPlugin 
{
 
   public static final boolean TRACE_ID_GEN_ENABLED =
-      Boolean.parseBoolean(EnvUtils.getProperty("solr.alwaysOnTraceId", 
"true"));
+      EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId", true);
 
   private static final String DEFAULT_CLASS_NAME =
       EnvUtils.getProperty(
           "solr.otelDefaultConfigurator", 
"org.apache.solr.opentelemetry.OtelTracerConfigurator");
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
-    if (info != null && info.isEnabled()) {
-      TracerConfigurator configurator =
-          loader.newInstance(info.className, TracerConfigurator.class);
-      configurator.init(info.initArgs);
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return configurator.getTracer();
-    }
-    if (shouldAutoConfigOTEL()) {
-      return autoConfigOTEL(loader);
+  /** Initializes {@link io.opentelemetry.api.GlobalOpenTelemetry} and returns 
a Tracer. */
+  public static synchronized Tracer loadTracer(SolrResourceLoader loader, 
PluginInfo info) {
+    // synchronized to avoid races in tests starting Solr concurrently setting 
GlobalOpenTelemetry
+    if (TraceUtils.OTEL_AGENT_PRESENT) {
+      log.info("OpenTelemetry Java agent was already installed; skipping OTEL 
initialization");
+    } else {
+      OpenTelemetry otel = null;
+      if (info != null && info.isEnabled()) {
+        var configurator = loader.newInstance(info.className, 
TracerConfigurator.class);
+        configurator.init(info.initArgs);
+        otel = configurator.createOtel();
+      } else if (shouldAutoConfigOTEL()) {
+        otel = autoConfigOTEL(loader); // could return null if failed to load
+        if (otel != null) {
+          log.info("OpenTelemetry loaded via auto configuration.");
+        }
+      }
+      if (otel == null && TRACE_ID_GEN_ENABLED) {
+        otel = 
OpenTelemetry.propagating(ContextPropagators.create(SimplePropagator.getInstance()));
+        log.info("OpenTelemetry loaded with simple propagation only.");
+      }
+      if (otel == null) {
+        otel = OpenTelemetry.noop();
+      }
+
+      try {
+        GlobalOpenTelemetry.set(otel); // throws IllegalStateException if 
already set
+        // skips needless ExecutorUtil.addThreadLocalProvider below
+        if (otel == OpenTelemetry.noop()) return otel.getTracer("solr");
+      } catch (IllegalStateException e) {
+        log.info("GlobalOpenTelemetry was already initialized (a Java agent?); 
using that");
+      }
     }
-    if (TRACE_ID_GEN_ENABLED) {
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return SimplePropagator.load();
-    }
-    return TraceUtils.getGlobalTracer();
+
+    ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());

Review Comment:
   Now called in exactly one spot, which I find easier to read than before



##########
solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java:
##########
@@ -49,14 +48,13 @@ public OtelTracerConfigurator() {
   }
 
   @Override
-  public Tracer getTracer() {
-    return TraceUtils.getGlobalTracer();

Review Comment:
   A needless GlobalOpenTelemetry reference



##########
solr/core/src/java/org/apache/solr/core/TracerConfigurator.java:
##########
@@ -38,33 +41,53 @@
 public abstract class TracerConfigurator implements NamedListInitializedPlugin 
{
 
   public static final boolean TRACE_ID_GEN_ENABLED =
-      Boolean.parseBoolean(EnvUtils.getProperty("solr.alwaysOnTraceId", 
"true"));
+      EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId", true);
 
   private static final String DEFAULT_CLASS_NAME =
       EnvUtils.getProperty(
           "solr.otelDefaultConfigurator", 
"org.apache.solr.opentelemetry.OtelTracerConfigurator");
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
-    if (info != null && info.isEnabled()) {
-      TracerConfigurator configurator =
-          loader.newInstance(info.className, TracerConfigurator.class);
-      configurator.init(info.initArgs);
-      ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
-      return configurator.getTracer();
-    }
-    if (shouldAutoConfigOTEL()) {
-      return autoConfigOTEL(loader);
+  /** Initializes {@link io.opentelemetry.api.GlobalOpenTelemetry} and returns 
a Tracer. */
+  public static synchronized Tracer loadTracer(SolrResourceLoader loader, 
PluginInfo info) {
+    // synchronized to avoid races in tests starting Solr concurrently setting 
GlobalOpenTelemetry

Review Comment:
   I didn't personally encounter an issue here but saw existing comments (from 
Alex?) that suggested to me making this synchronized would be helpful.  I don't 
think there's a true issue; ultimately GlobalOpenTelemetry will be set exactly 
once so it doesn't much matter if others try and race to do so.



##########
solr/modules/opentelemetry/src/test-files/solr/solr.xml:
##########
@@ -34,8 +34,6 @@
     <int name="connTimeout">${connTimeout:15000}</int>
   </shardHandlerFactory>
 
-  <tracerConfig name="tracerConfig" 
class="org.apache.solr.opentelemetry.CustomTestOtelTracerConfigurator" />

Review Comment:
   Perhaps this class could return but only for a test explicitly testing that 
tracerConfig works and in a separate solr.xml for exactly that test as well 
(not for the other tracing tests).  Not to be used for other tests or trying to 
collect spans for examination.



##########
solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java:
##########
@@ -49,14 +48,13 @@ public OtelTracerConfigurator() {
   }
 
   @Override
-  public Tracer getTracer() {
-    return TraceUtils.getGlobalTracer();
+  public void init(NamedList<?> args) {
+    prepareConfiguration(args);
   }
 
   @Override
-  public void init(NamedList<?> args) {
-    prepareConfiguration(args);
-    AutoConfiguredOpenTelemetrySdk.initialize();
+  public OpenTelemetry createOtel() {
+    return 
AutoConfiguredOpenTelemetrySdk.builder().build().getOpenTelemetrySdk();

Review Comment:
   notice the change to *not* call initialize.  That method arranges for 
GlobalOpenTelemetry to be set.  I only want that set in TracerConfigurator.



##########
solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/CustomTestOtelTracerConfigurator.java:
##########


Review Comment:
   this thing was strange; didn't need to exist, at least not as it existed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to