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

com.stripe.net.RequestTelemetry Maven / Gradle / Ivy

There is a newer version: 28.1.0-beta.3
Show newest version
package com.stripe.net;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.stripe.Stripe;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Data;

/** Helper class used by {@link LiveStripeResponseGetter} to manage request telemetry. */
class RequestTelemetry {
  /** The name of the header used to send request telemetry in requests. */
  public static final String HEADER_NAME = "X-Stripe-Client-Telemetry";

  private static final int MAX_REQUEST_METRICS_QUEUE_SIZE = 100;

  private static final Gson gson = new Gson();

  private static ConcurrentLinkedQueue prevRequestMetrics =
      new ConcurrentLinkedQueue();

  /**
   * Returns an {@link Optional} containing the value of the {@code X-Stripe-Telemetry} header to
   * add to the request. If the header is already present in the request, or if there is available
   * metrics, or if telemetry is disabled, then the returned {@code Optional} is empty.
   *
   * @param headers the request headers
   * @deprecated Use {$ling {@link #pollPayload()} instead.
   */
  @Deprecated
  public Optional getHeaderValue(HttpHeaders headers) {
    if (headers.firstValue(HEADER_NAME).isPresent()) {
      return Optional.empty();
    }

    return this.pollPayload();
  }

  public Optional pollPayload() {
    RequestMetrics requestMetrics = prevRequestMetrics.poll();
    if (requestMetrics == null) {
      return Optional.empty();
    }

    if (!Stripe.enableTelemetry) {
      return Optional.empty();
    }

    ClientTelemetryPayload payload = new ClientTelemetryPayload(requestMetrics);
    return Optional.of(gson.toJson(payload));
  }

  /**
   * If telemetry is enabled and the queue is not full, then enqueue a new metrics item; otherwise,
   * do nothing.
   *
   * @param response the Stripe response
   * @param duration the request duration
   * @param usage a list of tracked features used by the corresponding request
   */
  public void maybeEnqueueMetrics(
      AbstractStripeResponse response, Duration duration, List usage) {
    if (!Stripe.enableTelemetry) {
      return;
    }

    if (response.requestId() == null) {
      return;
    }

    if (prevRequestMetrics.size() >= MAX_REQUEST_METRICS_QUEUE_SIZE) {
      return;
    }

    if (usage != null && usage.size() == 0) {
      usage = null;
    }

    RequestMetrics metrics = new RequestMetrics(response.requestId(), duration.toMillis(), usage);
    prevRequestMetrics.add(metrics);
  }

  @Data
  private static class ClientTelemetryPayload {
    @SerializedName("last_request_metrics")
    private final RequestMetrics lastRequestMetrics;
  }

  @Data
  private static class RequestMetrics {
    @SerializedName("request_id")
    private final String requestId;

    @SerializedName("request_duration_ms")
    private final long requestDurationMs;

    @SerializedName("usage")
    private final List usage;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy