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

zipkin2.reporter.urlconnection.InternalURLConnectionSender Maven / Gradle / Ivy

There is a newer version: 3.5.1
Show newest version
/*
 * Copyright The OpenZipkin Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package zipkin2.reporter.urlconnection;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import zipkin2.reporter.BaseHttpSender;
import zipkin2.reporter.Component;

/**
 * We have to nest this class until v4 when {@linkplain URLConnectionSender} no longer needs to
 * extend {@linkplain Component}.
 */
final class InternalURLConnectionSender extends BaseHttpSender {

  final int messageMaxBytes;
  final int connectTimeout;
  final int readTimeout;
  final boolean compressionEnabled;

  InternalURLConnectionSender(URLConnectionSender.Builder builder) {
    super(builder.encoding, builder.endpointSupplierFactory, builder.endpoint);
    this.messageMaxBytes = builder.messageMaxBytes;
    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.compressionEnabled = builder.compressionEnabled;
  }

  @Override public int messageMaxBytes() {
    return messageMaxBytes;
  }

  @Override protected URL newEndpoint(String endpoint) {
    try {
      return new URL(endpoint);
    } catch (MalformedURLException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }

  @Override protected byte[] newBody(List encodedSpans) {
    return encoding.encode(encodedSpans);
  }

  @Override protected void postSpans(URL endpoint, byte[] body) throws IOException {
    // intentionally not closing the connection, to use keep-alives
    HttpURLConnection connection = (HttpURLConnection) endpoint.openConnection();
    connection.setConnectTimeout(connectTimeout);
    connection.setReadTimeout(readTimeout);
    connection.setRequestMethod("POST");
    // Amplification can occur when the Zipkin endpoint is proxied, and the proxy is instrumented.
    // This prevents that in proxies, such as Envoy, that understand B3 single format,
    connection.addRequestProperty("b3", "0");
    connection.addRequestProperty("Content-Type", encoding.mediaType());
    if (compressionEnabled) {
      connection.addRequestProperty("Content-Encoding", "gzip");
      ByteArrayOutputStream gzipped = new ByteArrayOutputStream();
      GZIPOutputStream compressor = new GZIPOutputStream(gzipped);
      try {
        compressor.write(body);
      } finally {
        compressor.close();
      }
      body = gzipped.toByteArray();
    }
    connection.setDoOutput(true);
    connection.setFixedLengthStreamingMode(body.length);
    connection.getOutputStream().write(body);

    skipAllContent(connection);
  }

  /** This utility is verbose as we have a minimum java version of 6 */
  static void skipAllContent(HttpURLConnection connection) throws IOException {
    InputStream in = connection.getInputStream();
    IOException thrown = skipAndSuppress(in);
    if (thrown == null) return;
    InputStream err = connection.getErrorStream();
    if (err != null) skipAndSuppress(err); // null is possible, if the connection was dropped
    throw thrown;
  }

  static IOException skipAndSuppress(InputStream in) {
    try {
      while (in.read() != -1) ; // skip
      return null;
    } catch (IOException e) {
      return e;
    } finally {
      try {
        in.close();
      } catch (IOException suppressed) {
      }
    }
  }

  @Override public String toString() {
    return super.toString().replace("Internal", "");
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy