content: /*
   * Copyright The OpenTelemetry Authors
   * SPDX-License-Identifier: Apache-2.0
   */
  
  package io.opentelemetry.instrumentation.runtimemetrics.java8;
  
  import io.opentelemetry.api.OpenTelemetry;
  import io.opentelemetry.api.metrics.Meter;
  import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
  import java.lang.management.ClassLoadingMXBean;
  import java.lang.management.ManagementFactory;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Registers measurements that generate metrics about JVM classes. The metrics generated by this
   * class follow <a
   * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
   * stable JVM metrics semantic conventions</a>.
   *
   * <p>Example usage:
   *
   * <pre>{@code
   * Classes.registerObservers(GlobalOpenTelemetry.get());
   * }</pre>
   *
   * <p>Example metrics being exported:
   *
   * <pre>
   *   jvm.class.loaded 100
   *   jvm.class.unloaded 2
   *   jvm.class.count 98
   * </pre>
   */
  public final class Classes {
  
    // Visible for testing
    static final Classes INSTANCE = new Classes();
  
    /** Register observers for java runtime class metrics. */
    public static List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry) {
      return INSTANCE.registerObservers(openTelemetry, ManagementFactory.getClassLoadingMXBean());
    }
  
    // Visible for testing
    List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry, ClassLoadingMXBean classBean) {
      Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
      List<AutoCloseable> observables = new ArrayList<>();
  
      observables.add(
          meter
              .counterBuilder("jvm.class.loaded")
              .setDescription("Number of classes loaded since JVM start.")
              .setUnit("{class}")
              .buildWithCallback(
                  observableMeasurement ->
                      observableMeasurement.record(classBean.getTotalLoadedClassCount())));
      observables.add(
          meter
              .counterBuilder("jvm.class.unloaded")
              .setDescription("Number of classes unloaded since JVM start.")
              .setUnit("{class}")
              .buildWithCallback(
                  observableMeasurement ->
                      observableMeasurement.record(classBean.getUnloadedClassCount())));
      observables.add(
          meter
              .upDownCounterBuilder("jvm.class.count")
              .setDescription("Number of classes currently loaded.")
              .setUnit("{class}")
              .buildWithCallback(
                  observableMeasurement ->
                      observableMeasurement.record(classBean.getLoadedClassCount())));
  
      return observables;
    }
  
    private Classes() {}
  }
  