Repository: open-telemetry/opentelemetry-java
File: sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/export/PeriodicMetricReader.java (Java)

Code before:
        + intervalNanos
        + '}';
  }

  void start() {
    synchronized (lock) {
      if (scheduledFuture != null) {
        return;
      }
      scheduledFuture =
          scheduler.scheduleAtFixedRate(
              scheduled, intervalNanos, intervalNanos, TimeUnit.NANOSECONDS);
    }
  }

  private final class Scheduled implements Runnable {

    private final AtomicBoolean exportAvailable = new AtomicBoolean(true);

    private MetricReaderInstrumentation instrumentation =
        new MetricReaderInstrumentation(COMPONENT_ID, MeterProvider.noop());

    private Scheduled() {}

    void setMeterProvider(MeterProvider meterProvider) {
      instrumentation = new MetricReaderInstrumentation(COMPONENT_ID, meterProvider);
    }

    @Override
    public void run() {
      // Ignore the CompletableResultCode from doRun() in order to keep run() asynchronous
      doRun();
    }

    // Runs a collect + export cycle.
    CompletableResultCode doRun() {
      CompletableResultCode flushResult = new CompletableResultCode();
      if (exportAvailable.compareAndSet(true, false)) {
        try {
          long startNanoTime = CLOCK.nanoTime();
          String error = null;
          Collection<MetricData> metricData;
          try {
            metricData = collectionRegistration.collectAllMetrics();
          } catch (Throwable t) {
            error = t.getClass().getName();
            throw t;
          } finally {
            long durationNanos = CLOCK.nanoTime() - startNanoTime;
            instrumentation.recordCollection(durationNanos / 1_000_000_000.0, error);
          }

Review comment (suggestion):
```suggestion
    private void setMeterProvider(MeterProvider meterProvider) {
```

Code after:
        + ", intervalNanos="
        + intervalNanos
        + '}';
  }

  void start() {
    synchronized (lock) {
      if (scheduledFuture != null) {
        return;
      }
      scheduledFuture =
          scheduler.scheduleAtFixedRate(
              scheduled, intervalNanos, intervalNanos, TimeUnit.NANOSECONDS);
    }
  }

  private final class Scheduled implements Runnable {

    private final AtomicBoolean exportAvailable = new AtomicBoolean(true);

    private MetricReaderInstrumentation instrumentation =
        new MetricReaderInstrumentation(COMPONENT_ID, MeterProvider.noop());

    private Scheduled() {}

    void setMeterProvider(MeterProvider meterProvider) {
      instrumentation = new MetricReaderInstrumentation(COMPONENT_ID, meterProvider);
    }

    @Override
    public void run() {
      // Ignore the CompletableResultCode from doRun() in order to keep run() asynchronous
      doRun();
    }

    // Runs a collect + export cycle.
    CompletableResultCode doRun() {
      CompletableResultCode flushResult = new CompletableResultCode();
      if (exportAvailable.compareAndSet(true, false)) {
        try {
          long startNanoTime = CLOCK.nanoTime();
          String error = null;
          Collection<MetricData> metricData;
          try {
            metricData = collectionRegistration.collectAllMetrics();
          } finally {
            long durationNanos = CLOCK.nanoTime() - startNanoTime;
            instrumentation.recordCollection(durationNanos / 1_000_000_000.0, error);
          }
          if (metricData.isEmpty()) {
            logger.log(Level.FINE, "No metric data to export - skipping export.");