mirror of
				https://github.com/scm-manager/scm-manager.git
				synced 2025-11-03 12:05:52 +01:00 
			
		
		
		
	Integrate trace api with AdvancedHttpClient
This commit is contained in:
		@@ -26,18 +26,16 @@ package sonia.scm.net.ahc;
 | 
			
		||||
 | 
			
		||||
//~--- non-JDK imports --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Charsets;
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import com.google.common.collect.LinkedHashMultimap;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
 | 
			
		||||
import org.apache.shiro.codec.Base64;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.util.HttpUtil;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for http requests.
 | 
			
		||||
@@ -102,7 +100,7 @@ public abstract class BaseHttpRequest<T extends BaseHttpRequest>
 | 
			
		||||
    String auth = Strings.nullToEmpty(username).concat(":").concat(
 | 
			
		||||
                    Strings.nullToEmpty(password));
 | 
			
		||||
 | 
			
		||||
    auth = Base64.encodeToString(auth.getBytes(Charsets.ISO_8859_1));
 | 
			
		||||
    auth = Base64.encodeToString(auth.getBytes(StandardCharsets.ISO_8859_1));
 | 
			
		||||
    headers.put("Authorization", "Basic ".concat(auth));
 | 
			
		||||
 | 
			
		||||
    return self();
 | 
			
		||||
@@ -246,6 +244,19 @@ public abstract class BaseHttpRequest<T extends BaseHttpRequest>
 | 
			
		||||
    return self();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the kind of span for tracing api.
 | 
			
		||||
   *
 | 
			
		||||
   * @param spanKind kind of span
 | 
			
		||||
   * @return request instance
 | 
			
		||||
   *
 | 
			
		||||
   * @since 2.9.0
 | 
			
		||||
   */
 | 
			
		||||
  public T spanKind(String spanKind) {
 | 
			
		||||
    this.spanKind = spanKind;
 | 
			
		||||
    return self();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- get methods ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -281,6 +292,17 @@ public abstract class BaseHttpRequest<T extends BaseHttpRequest>
 | 
			
		||||
    return url;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns the kind of span which is used for the trace api.
 | 
			
		||||
   *
 | 
			
		||||
   * @return kind of span
 | 
			
		||||
   *
 | 
			
		||||
   * @since 2.9.0
 | 
			
		||||
   */
 | 
			
		||||
  public String getSpanKind() {
 | 
			
		||||
    return spanKind;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns true if the request decodes gzip compression.
 | 
			
		||||
   *
 | 
			
		||||
@@ -398,4 +420,7 @@ public abstract class BaseHttpRequest<T extends BaseHttpRequest>
 | 
			
		||||
 | 
			
		||||
  /** url of request */
 | 
			
		||||
  private String url;
 | 
			
		||||
 | 
			
		||||
  /** kind of span for trace api */
 | 
			
		||||
  private String spanKind = "http-request";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,8 +38,11 @@ import sonia.scm.config.ScmConfiguration;
 | 
			
		||||
import sonia.scm.net.Proxies;
 | 
			
		||||
import sonia.scm.net.TrustAllHostnameVerifier;
 | 
			
		||||
import sonia.scm.net.TrustAllTrustManager;
 | 
			
		||||
import sonia.scm.trace.Span;
 | 
			
		||||
import sonia.scm.trace.Tracer;
 | 
			
		||||
import sonia.scm.util.HttpUtil;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.inject.Provider;
 | 
			
		||||
import javax.net.ssl.HttpsURLConnection;
 | 
			
		||||
import javax.net.ssl.SSLContext;
 | 
			
		||||
@@ -99,9 +102,10 @@ public class DefaultAdvancedHttpClient extends AdvancedHttpClient
 | 
			
		||||
   */
 | 
			
		||||
  @Inject
 | 
			
		||||
  public DefaultAdvancedHttpClient(ScmConfiguration configuration,
 | 
			
		||||
    Set<ContentTransformer> contentTransformers, Provider<SSLContext> sslContextProvider)
 | 
			
		||||
    Tracer tracer, Set<ContentTransformer> contentTransformers, Provider<SSLContext> sslContextProvider)
 | 
			
		||||
  {
 | 
			
		||||
    this.configuration = configuration;
 | 
			
		||||
    this.tracer = tracer;
 | 
			
		||||
    this.contentTransformers = contentTransformers;
 | 
			
		||||
    this.sslContextProvider = sslContextProvider;
 | 
			
		||||
  }
 | 
			
		||||
@@ -185,45 +189,48 @@ public class DefaultAdvancedHttpClient extends AdvancedHttpClient
 | 
			
		||||
   * @throws IOException
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  protected AdvancedHttpResponse request(BaseHttpRequest<?> request)
 | 
			
		||||
    throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    HttpURLConnection connection = openConnection(request,
 | 
			
		||||
                                     new URL(request.getUrl()));
 | 
			
		||||
  protected AdvancedHttpResponse request(BaseHttpRequest<?> request) throws IOException {
 | 
			
		||||
    try (Span span = tracer.span(request.getSpanKind())) {
 | 
			
		||||
      span.label("url", request.getUrl());
 | 
			
		||||
      span.label("method", request.getMethod());
 | 
			
		||||
      DefaultAdvancedHttpResponse response = doRequest(request);
 | 
			
		||||
      span.label("status", response.getStatus());
 | 
			
		||||
      if (!response.isSuccessful()) {
 | 
			
		||||
        span.failed();
 | 
			
		||||
      }
 | 
			
		||||
      return response;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Nonnull
 | 
			
		||||
  private DefaultAdvancedHttpResponse doRequest(BaseHttpRequest<?> request) throws IOException {
 | 
			
		||||
    HttpURLConnection connection = openConnection(request, new URL(request.getUrl()));
 | 
			
		||||
 | 
			
		||||
    applyBaseSettings(request, connection);
 | 
			
		||||
 | 
			
		||||
    if (connection instanceof HttpsURLConnection)
 | 
			
		||||
    {
 | 
			
		||||
    if (connection instanceof HttpsURLConnection) {
 | 
			
		||||
      applySSLSettings(request, (HttpsURLConnection) connection);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Content content = null;
 | 
			
		||||
 | 
			
		||||
    if (request instanceof AdvancedHttpRequestWithBody)
 | 
			
		||||
    {
 | 
			
		||||
    if (request instanceof AdvancedHttpRequestWithBody) {
 | 
			
		||||
      AdvancedHttpRequestWithBody ahrwb = (AdvancedHttpRequestWithBody) request;
 | 
			
		||||
 | 
			
		||||
      content = ahrwb.getContent();
 | 
			
		||||
 | 
			
		||||
      if (content != null)
 | 
			
		||||
      {
 | 
			
		||||
      if (content != null) {
 | 
			
		||||
        content.prepare(ahrwb);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
      } else {
 | 
			
		||||
        request.header(HttpUtil.HEADER_CONTENT_LENGTH, "0");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    } else {
 | 
			
		||||
      request.header(HttpUtil.HEADER_CONTENT_LENGTH, "0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    applyHeaders(request, connection);
 | 
			
		||||
 | 
			
		||||
    if (content != null)
 | 
			
		||||
    {
 | 
			
		||||
    if (content != null) {
 | 
			
		||||
      applyContent(connection, content);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -383,4 +390,7 @@ public class DefaultAdvancedHttpClient extends AdvancedHttpClient
 | 
			
		||||
 | 
			
		||||
  /** ssl context provider */
 | 
			
		||||
  private final Provider<SSLContext> sslContextProvider;
 | 
			
		||||
 | 
			
		||||
  /** tracer used for request tracing */
 | 
			
		||||
  private Tracer tracer;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,11 +30,14 @@ import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
import org.mockito.Answers;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.config.ScmConfiguration;
 | 
			
		||||
import sonia.scm.net.TrustAllHostnameVerifier;
 | 
			
		||||
import sonia.scm.trace.Span;
 | 
			
		||||
import sonia.scm.trace.Tracer;
 | 
			
		||||
import sonia.scm.util.HttpUtil;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.*;
 | 
			
		||||
@@ -265,6 +268,32 @@ public class DefaultAdvancedHttpClientTest
 | 
			
		||||
      "Basic dHJpY2lhOnRyaWNpYXMgc2VjcmV0");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void shouldCreateTracingSpan() throws IOException {
 | 
			
		||||
    when(connection.getResponseCode()).thenReturn(200);
 | 
			
		||||
 | 
			
		||||
    new AdvancedHttpRequest(client, HttpMethod.GET, "https://www.scm-manager.org").spanKind("spaceships").request();
 | 
			
		||||
    verify(tracer).span("spaceships");
 | 
			
		||||
    verify(span).label("url", "https://www.scm-manager.org");
 | 
			
		||||
    verify(span).label("method", "GET");
 | 
			
		||||
    verify(span).label("status", 200);
 | 
			
		||||
    verify(span, never()).failed();
 | 
			
		||||
    verify(span).close();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void shouldCreateFailedTracingSpan() throws IOException {
 | 
			
		||||
    when(connection.getResponseCode()).thenReturn(500);
 | 
			
		||||
 | 
			
		||||
    new AdvancedHttpRequest(client, HttpMethod.GET, "https://www.scm-manager.org").request();
 | 
			
		||||
    verify(tracer).span("http-request");
 | 
			
		||||
    verify(span).label("url", "https://www.scm-manager.org");
 | 
			
		||||
    verify(span).label("method", "GET");
 | 
			
		||||
    verify(span).label("status", 500);
 | 
			
		||||
    verify(span).failed();
 | 
			
		||||
    verify(span).close();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- set methods ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -277,6 +306,7 @@ public class DefaultAdvancedHttpClientTest
 | 
			
		||||
    configuration = new ScmConfiguration();
 | 
			
		||||
    transformers = new HashSet<ContentTransformer>();
 | 
			
		||||
    client = new TestingAdvacedHttpClient(configuration, transformers);
 | 
			
		||||
    when(tracer.span(anyString())).thenReturn(span);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- inner classes --------------------------------------------------------
 | 
			
		||||
@@ -298,10 +328,9 @@ public class DefaultAdvancedHttpClientTest
 | 
			
		||||
     * @param configuration
 | 
			
		||||
     * @param transformers
 | 
			
		||||
     */
 | 
			
		||||
    public TestingAdvacedHttpClient(ScmConfiguration configuration,
 | 
			
		||||
      Set<ContentTransformer> transformers)
 | 
			
		||||
    public TestingAdvacedHttpClient(ScmConfiguration configuration, Set<ContentTransformer> transformers)
 | 
			
		||||
    {
 | 
			
		||||
      super(configuration, transformers, new SSLContextProvider());
 | 
			
		||||
      super(configuration, tracer, transformers, new SSLContextProvider());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //~--- methods ------------------------------------------------------------
 | 
			
		||||
@@ -364,4 +393,10 @@ public class DefaultAdvancedHttpClientTest
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private Set<ContentTransformer> transformers;
 | 
			
		||||
 | 
			
		||||
  @Mock
 | 
			
		||||
  private Tracer tracer;
 | 
			
		||||
 | 
			
		||||
  @Mock
 | 
			
		||||
  private Span span;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,9 +33,11 @@ import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.common.io.ByteSource;
 | 
			
		||||
 | 
			
		||||
import org.hamcrest.Matchers;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
import org.mockito.Answers;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +58,7 @@ import java.util.HashSet;
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import sonia.scm.net.SSLContextProvider;
 | 
			
		||||
import sonia.scm.trace.Tracer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,6 +68,13 @@ import sonia.scm.net.SSLContextProvider;
 | 
			
		||||
public class DefaultAdvancedHttpResponseTest
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  private DefaultAdvancedHttpClient client;
 | 
			
		||||
 | 
			
		||||
  @Before
 | 
			
		||||
  public void setUpClient() {
 | 
			
		||||
    client = new DefaultAdvancedHttpClient(new ScmConfiguration(), tracer, new HashSet<>(), new SSLContextProvider());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
@@ -130,13 +140,10 @@ public class DefaultAdvancedHttpResponseTest
 | 
			
		||||
    assertTrue(headers.get("Test-2").isEmpty());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- fields ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private final DefaultAdvancedHttpClient client =
 | 
			
		||||
    new DefaultAdvancedHttpClient(new ScmConfiguration(), new HashSet<>(), new SSLContextProvider());
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  @Mock
 | 
			
		||||
  private HttpURLConnection connection;
 | 
			
		||||
 | 
			
		||||
  @Mock(answer = Answers.RETURNS_DEEP_STUBS)
 | 
			
		||||
  private Tracer tracer;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user