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

com.datadoghq.trace.writer.DDApi Maven / Gradle / Ivy

package com.datadoghq.trace.writer;

import com.datadoghq.trace.DDBaseSpan;
import com.datadoghq.trace.DDTraceInfo;
import com.datadoghq.trace.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.util.concurrent.RateLimiter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.msgpack.jackson.dataformat.MessagePackFactory;

/** The API pointing to a DD agent */
@Slf4j
public class DDApi {

  private static final String TRACES_ENDPOINT = "/v0.3/traces";
  private static final String SERVICES_ENDPOINT = "/v0.3/services";
  private static final long SECONDS_BETWEEN_ERROR_LOG = TimeUnit.MINUTES.toSeconds(5);

  private final String tracesEndpoint;
  private final String servicesEndpoint;

  private final RateLimiter loggingRateLimiter =
      RateLimiter.create(1.0 / SECONDS_BETWEEN_ERROR_LOG);

  private final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());

  public DDApi(final String host, final int port) {
    this.tracesEndpoint = "http://" + host + ":" + port + TRACES_ENDPOINT;
    this.servicesEndpoint = "http://" + host + ":" + port + SERVICES_ENDPOINT;
  }

  /**
   * Send traces to the DD agent
   *
   * @param traces the traces to be sent
   * @return the staus code returned
   */
  public boolean sendTraces(final List>> traces) {
    return putContent("traces", tracesEndpoint, traces, traces.size());
  }

  /**
   * Send service extra information to the services endpoint
   *
   * @param services the services to be sent
   */
  public boolean sendServices(final Map services) {
    if (services == null) {
      return true;
    }
    return putContent("services", servicesEndpoint, services, services.size());
  }

  /**
   * PUT to an endpoint the provided JSON content
   *
   * @param content
   * @return the status code
   */
  private boolean putContent(
      final String type, final String endpoint, final Object content, final int size) {
    try {
      final HttpURLConnection httpCon = getHttpURLConnection(endpoint);

      final OutputStream out = httpCon.getOutputStream();
      objectMapper.writeValue(out, content);
      out.flush();
      out.close();

      final int responseCode = httpCon.getResponseCode();
      if (responseCode != 200) {
        if (log.isDebugEnabled()) {
          log.debug(
              "Error while sending {} {} to the DD agent. Status: {}, ResponseMessage: ",
              size,
              type,
              responseCode,
              httpCon.getResponseMessage());
        } else if (loggingRateLimiter.tryAcquire()) {
          log.warn(
              "Error while sending {} {} to the DD agent. Status: {} (going silent for {} seconds)",
              size,
              type,
              responseCode,
              httpCon.getResponseMessage(),
              SECONDS_BETWEEN_ERROR_LOG);
        }
        return false;
      }

      log.debug("Succesfully sent {} {} to the DD agent.", size, type);
      return true;

    } catch (final IOException e) {
      if (log.isDebugEnabled()) {
        log.debug("Error while sending " + size + " " + type + " to the DD agent.", e);
      } else if (loggingRateLimiter.tryAcquire()) {
        log.warn(
            "Error while sending {} {} to the DD agent. Message: {} (going silent for {} seconds)",
            size,
            type,
            e.getMessage(),
            SECONDS_BETWEEN_ERROR_LOG);
      }
      return false;
    }
  }

  private HttpURLConnection getHttpURLConnection(final String endpoint) throws IOException {
    final HttpURLConnection httpCon;
    final URL url = new URL(endpoint);
    httpCon = (HttpURLConnection) url.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setRequestMethod("PUT");
    httpCon.setRequestProperty("Content-Type", "application/msgpack");
    httpCon.setRequestProperty("Datadog-Meta-Lang", "java");
    httpCon.setRequestProperty("Datadog-Meta-Lang-Version", DDTraceInfo.JAVA_VERSION);
    httpCon.setRequestProperty("Datadog-Meta-Lang-Interpreter", DDTraceInfo.JAVA_VM_NAME);
    httpCon.setRequestProperty("Datadog-Meta-Tracer-Version", DDTraceInfo.VERSION);
    return httpCon;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy