All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wavefront.sdk.grpc.reporter.WavefrontGrpcReporter Maven / Gradle / Ivy

The newest version!
package com.wavefront.sdk.grpc.reporter;

import com.google.common.annotations.VisibleForTesting;
import com.wavefront.internal.reporter.SdkReporter;
import com.wavefront.internal.reporter.WavefrontInternalReporter;
import com.wavefront.internal_reporter_java.io.dropwizard.metrics5.MetricName;
import com.wavefront.sdk.common.Utils;
import com.wavefront.sdk.common.WavefrontSender;
import com.wavefront.sdk.common.application.ApplicationTags;
import com.wavefront.sdk.common.application.HeartbeaterService;
import com.wavefront.sdk.entities.metrics.WavefrontMetricSender;

import javax.annotation.Nullable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;

import static com.wavefront.sdk.common.Constants.APPLICATION_TAG_KEY;
import static com.wavefront.sdk.common.Constants.SDK_METRIC_PREFIX;
import static com.wavefront.sdk.grpc.Constants.GRPC_CLIENT_COMPONENT;
import static com.wavefront.sdk.grpc.Constants.GRPC_SERVER_COMPONENT;

/**
 * Wavefront reporter for your gRPC based application responsible for reporting metrics and
 * histograms out of the box for you. Typically this is instantiated once per service and passed
 * to grpc client/server tracers/interceptors.
 *
 * @author Srujan Narkedamalli ([email protected]).
 */
public class WavefrontGrpcReporter implements SdkReporter {
  private static final Logger logger =
      Logger.getLogger(WavefrontGrpcReporter.class.getCanonicalName());
  private final int reportingIntervalSeconds;
  private final WavefrontInternalReporter wfReporter;
  private final WavefrontInternalReporter sdkMetricsReporter;
  private final WavefrontMetricSender wfMetricSender;
  private final ApplicationTags applicationTags;
  private final String source;
  private HeartbeaterService clientHeartbeat;
  private HeartbeaterService serverHeartbeat;

  @VisibleForTesting
  @Deprecated
  WavefrontGrpcReporter(WavefrontInternalReporter wfReporter, int reportingIntervalSeconds,
                        WavefrontMetricSender wfMetricSender,
                        ApplicationTags applicationTags, String source) {
    this(wfReporter, reportingIntervalSeconds, wfMetricSender, applicationTags, source, null);
  }

  @VisibleForTesting
  WavefrontGrpcReporter(WavefrontInternalReporter wfReporter, int reportingIntervalSeconds,
                        WavefrontMetricSender wfMetricSender,
                        ApplicationTags applicationTags, String source,
                        WavefrontInternalReporter sdkMetricsReporter) {
    this.wfReporter = wfReporter;
    this.reportingIntervalSeconds = reportingIntervalSeconds;
    this.wfMetricSender = wfMetricSender;
    this.applicationTags = applicationTags;
    this.source = source;
    this.sdkMetricsReporter = sdkMetricsReporter;
  }

  @Override
  public void incrementCounter(MetricName metricName) {
    wfReporter.newCounter(metricName).inc();
  }

  @Override
  public void incrementCounter(MetricName metricName, long incrementValue) {
    wfReporter.newCounter(metricName).inc(incrementValue);
  }

  @Override
  public void incrementDeltaCounter(MetricName metricName) {
    wfReporter.newDeltaCounter(metricName).inc();
  }

  public void registerGauge(MetricName metricName, Supplier value) {
    wfReporter.newGauge(metricName, () -> value::get);
  }

  @Override
  public void updateHistogram(MetricName metricName, long latencyMillis) {
    wfReporter.newWavefrontHistogram(metricName).update(latencyMillis);
  }

  @Override
  public void registerGauge(MetricName metricName, AtomicInteger atomicInteger) {
    wfReporter.newGauge(metricName, () -> (() -> (double) atomicInteger.get()));
  }

  @Override
  public void start() {
    wfReporter.start(reportingIntervalSeconds, TimeUnit.SECONDS);
    if (sdkMetricsReporter != null) {
      sdkMetricsReporter.start(1, TimeUnit.MINUTES);
    }
  }

  @Override
  public void stop() {
    if (serverHeartbeat != null) {
      serverHeartbeat.close();
    }
    if (clientHeartbeat != null) {
      clientHeartbeat.close();
    }
    if (wfReporter != null) {
      wfReporter.stop();
    }
    if (sdkMetricsReporter != null) {
      sdkMetricsReporter.stop();
    }
  }

  public synchronized void registerServerHeartBeat() {
    if (serverHeartbeat == null) {
      serverHeartbeat = new HeartbeaterService(wfMetricSender, applicationTags,
          Collections.singletonList(GRPC_SERVER_COMPONENT), source);
    }
  }

  public synchronized void registerClientHeartbeat() {
    if (clientHeartbeat == null) {
      clientHeartbeat = new HeartbeaterService(wfMetricSender, applicationTags,
          Collections.singletonList(GRPC_CLIENT_COMPONENT), source);
    }
  }

  public static class Builder {
    // Required parameters
    private final ApplicationTags applicationTags;
    private final String prefix = "grpc";

    // Optional parameters
    private int reportingIntervalSeconds = 60;

    @Nullable
    private String source;

    /**
     * Builder to build WavefrontGrpcReporter.
     *
     * @param applicationTags  metadata about your application that you want to be propagated as
     *                         tags when metrics/histograms are sent to Wavefront.
     */
    public Builder(ApplicationTags applicationTags) {
      this.applicationTags = applicationTags;
    }

    /**
     * Set reporting interval i.e. how often you want to report the metrics/histograms to
     * Wavefront.
     *
     * @param reportingIntervalSeconds reporting interval in seconds.
     * @return {@code this}.
     */
    public Builder reportingIntervalSeconds(int reportingIntervalSeconds) {
      this.reportingIntervalSeconds = reportingIntervalSeconds;
      return this;
    }

    /**
     * Set the source tag for your metric and histograms.
     *
     * @param source Name of the source/host where your application is running.
     * @return {@code this}.
     */
    public Builder withSource(String source) {
      this.source = source;
      return this;
    }

    /**
     * Build a WavefrontGrpcReporter.
     *
     * @param wavefrontSender send data to Wavefront via proxy or direct ingestion.
     * @return An instance of {@link WavefrontGrpcReporter}.
     */
    public WavefrontGrpcReporter build(WavefrontSender wavefrontSender) {
      if (source == null) {
        try {
          source = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
          // Should never happen
          logger.log(Level.SEVERE, "source name not known, setting to unknown", e);
          source = "unknown";
        }
      }
      // application tag is reported with every metric
      Map pointTags = new HashMap<>();
      pointTags.put(APPLICATION_TAG_KEY, applicationTags.getApplication());
      if (applicationTags.getCustomTags() != null) {
        pointTags.putAll(applicationTags.getCustomTags());
      }
      WavefrontInternalReporter wfReporter = new WavefrontInternalReporter.Builder().
          prefixedWith(prefix).withSource(source).withReporterPointTags(pointTags).
          reportMinuteDistribution().build(wavefrontSender);

      WavefrontInternalReporter sdkMetricsReporter = new WavefrontInternalReporter.Builder().
          prefixedWith(SDK_METRIC_PREFIX + ".grpc").withSource(source).
          withReporterPointTags(pointTags).build(wavefrontSender);

      double sdkVersion = Utils.getSemVerGauge("wavefront-grpc-sdk-java");
      sdkMetricsReporter.newGauge(new MetricName("version", Collections.emptyMap()),
          () -> (() -> sdkVersion));

      return new WavefrontGrpcReporter(wfReporter, reportingIntervalSeconds, wavefrontSender,
          applicationTags, source, sdkMetricsReporter);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy