Repository: open-telemetry/opentelemetry-java
File: api/all/src/main/java/io/opentelemetry/api/GlobalOpenTelemetry.java (Java)

Code before:
   * <p>If you are using the OpenTelemetry SDK, you should generally use {@code
   * OpenTelemetrySdk.builder().buildAndRegisterGlobal()} instead of calling this method directly.
   */
  public static void set(OpenTelemetry openTelemetry) {
    synchronized (mutex) {
      if (globalOpenTelemetry != null) {
        throw new IllegalStateException(
            "GlobalOpenTelemetry.set has already been called. GlobalOpenTelemetry.set must be "
                + "called only once before any calls to GlobalOpenTelemetry.get. If you are using "
                + "the OpenTelemetrySdk, use OpenTelemetrySdkBuilder.buildAndRegisterGlobal "
                + "instead. Previous invocation set to cause of this exception.",
            setGlobalCaller);
      }
      globalOpenTelemetry = new ObfuscatedOpenTelemetry(openTelemetry);
      setGlobalCaller = new Throwable();
    }
  }

  /**
   * Sets the {@link OpenTelemetry} that should be the global instance.
   *
   * <p>This method calls the given {@code supplier}, converts the output to an {@link
   * OpenTelemetry} object, and finally calls {@link #set(OpenTelemetry)}, all while holding the
   * {@link GlobalOpenTelemetry} mutex.
   */
  public static <T> T set(Supplier<T> supplier, Function<T, OpenTelemetry> converter) {
    synchronized (mutex) {
      T output = supplier.get();
      set(converter.apply(output));
      return output;
    }
  }

  /** Returns the globally registered {@link TracerProvider}. */
  public static TracerProvider getTracerProvider() {
    return get().getTracerProvider();
  }

  /**
   * Gets or creates a named tracer instance from the globally registered {@link TracerProvider}.
   *
   * <p>This is a shortcut method for {@code getTracerProvider().get(instrumentationScopeName)}
   *
   * @param instrumentationScopeName A name uniquely identifying the instrumentation scope, such as
   *     the instrumentation library, package, or fully qualified class name. Must not be null.
   * @return a tracer instance.
   */
  public static Tracer getTracer(String instrumentationScopeName) {
    return get().getTracer(instrumentationScopeName);
  }


Review comment (suggestion):
What about something like: https://github.com/open-telemetry/opentelemetry-java/commit/5f06de2b8aeca6a41157a88d3abaab3bd23dbded

This API signature will look strange outside of the autoconfigure use case.

I like this approach in general though and would love to get it merged!

Code after:
   * OpenTelemetrySdk.builder().buildAndRegisterGlobal()} instead of calling this method directly.
   */
  public static void set(OpenTelemetry openTelemetry) {
    synchronized (mutex) {
      if (globalOpenTelemetry != null) {
        throw new IllegalStateException(
            "GlobalOpenTelemetry.set has already been called. GlobalOpenTelemetry.set must be "
                + "called only once before any calls to GlobalOpenTelemetry.get. If you are using "
                + "the OpenTelemetrySdk, use OpenTelemetrySdkBuilder.buildAndRegisterGlobal "
                + "instead. Previous invocation set to cause of this exception.",
            setGlobalCaller);
      }
      globalOpenTelemetry = new ObfuscatedOpenTelemetry(openTelemetry);
      setGlobalCaller = new Throwable();
    }
  }

  /**
   * Sets the {@link OpenTelemetry} that should be the global instance.
   *
   * <p>This method calls the given {@code supplier} and calls {@link #set(OpenTelemetry)}, all
   * while holding the {@link GlobalOpenTelemetry} mutex.
   */
  public static void set(Supplier<OpenTelemetry> supplier) {
    synchronized (mutex) {
      OpenTelemetry openTelemetry = supplier.get();
      set(openTelemetry);
    }
  }

  /** Returns the globally registered {@link TracerProvider}. */
  public static TracerProvider getTracerProvider() {
    return get().getTracerProvider();
  }

  /**
   * Gets or creates a named tracer instance from the globally registered {@link TracerProvider}.
   *
   * <p>This is a shortcut method for {@code getTracerProvider().get(instrumentationScopeName)}
   *
   * @param instrumentationScopeName A name uniquely identifying the instrumentation scope, such as
   *     the instrumentation library, package, or fully qualified class name. Must not be null.
   * @return a tracer instance.
   */
  public static Tracer getTracer(String instrumentationScopeName) {
    return get().getTracer(instrumentationScopeName);
  }

  /**
   * Gets or creates a named and versioned tracer instance from the globally registered {@link
   * TracerProvider}.