diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 42e9fe304..b48b8b337 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -3,6 +3,7 @@ import java.io.IOException; import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.Interceptor; import okhttp3.Request; @@ -21,6 +22,11 @@ public AuthenticationHandler(ICoreAuthenticationProvider authProvider) { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); + + if(originalRequest.tag(TelemetryOptions.class) == null) + originalRequest = originalRequest.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); + originalRequest.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + Request authenticatedRequest = authProvider.authenticateRequest(originalRequest); return chain.proceed(authenticatedRequest); } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 4084ae91d..144173609 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -1,5 +1,6 @@ package com.microsoft.graph.httpcore; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.OkHttpClient.Builder; @@ -30,6 +31,22 @@ public static OkHttpClient createDefault(ICoreAuthenticationProvider auth) { .followRedirects(false) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) + .addInterceptor(new TelemetryHandler()) .build(); } + + /** + * Creates {@link OkHttpClient} instance with interceptors + * + * @param interceptors Use interceptors provided while constructing http client + * @return OkHttpClient build with interceptors provided + */ + public static OkHttpClient createFromInterceptors(Interceptor[] interceptors) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + for(Interceptor interceptor : interceptors) { + builder.addInterceptor(interceptor); + } + builder.addInterceptor(new TelemetryHandler()); + return builder.build(); + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index dbc866990..78c3aa787 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -11,6 +11,7 @@ import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.HttpUrl; import okhttp3.Interceptor; @@ -100,6 +101,11 @@ Request getRedirect( @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); + + if(request.tag(TelemetryOptions.class) == null) + request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); + request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + Response response = null; int requestsCount = 1; diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 5d8b18fc8..a8f542398 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -5,6 +5,7 @@ import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.Interceptor; import okhttp3.Request; @@ -124,6 +125,11 @@ boolean isBuffered(Response response, Request request) { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); + + if(request.tag(TelemetryOptions.class) == null) + request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); + request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + Response response = chain.proceed(request); // Use should retry pass along with this request diff --git a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java new file mode 100644 index 000000000..9bcd75d3f --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java @@ -0,0 +1,38 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; + +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class TelemetryHandler implements Interceptor{ + + public static final String SDK_VERSION = "SdkVersion"; + public static final String VERSION = "v0.1.0-SNAPSHOT"; + public static final String GRAPH_VERSION_PREFIX = "graph-java-core"; + public static final String CLIENT_REQUEST_ID = "client-request-id"; + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request.Builder telemetryAddedBuilder = request.newBuilder(); + + TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + + if(telemetryOptions != null) { + String featureUsage = "(featureUsage=" + telemetryOptions.getFeatureUsage() + ")"; + String sdkversion_value = GRAPH_VERSION_PREFIX + "/" + VERSION + " " + featureUsage; + telemetryAddedBuilder.addHeader(SDK_VERSION, sdkversion_value); + + if(request.header(CLIENT_REQUEST_ID) == null) { + telemetryAddedBuilder.addHeader(CLIENT_REQUEST_ID, telemetryOptions.getClientRequestId()); + } + } + + return chain.proceed(telemetryAddedBuilder.build()); + } + +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java new file mode 100644 index 000000000..60def57d8 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java @@ -0,0 +1,36 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import java.util.UUID; + +public class TelemetryOptions { + + public static final int NONE_FLAG = 0; + public static final int REDIRECT_HANDLER_ENABLED_FLAG = 1; + public static final int RETRY_HANDLER_ENABLED_FLAG = 2; + public static final int AUTH_HANDLER_ENABLED_FLAG = 4; + public static final int DEFAULT_HTTPROVIDER_ENABLED_FLAG = 8; + public static final int LOGGING_HANDLER_ENABLED_FLAG = 16; + + private int featureUsage = NONE_FLAG; + private String clientRequestId; + + public void setFeatureUsage(int flag) { + featureUsage = featureUsage | flag; + } + + public String getFeatureUsage() { + return Integer.toHexString(featureUsage); + } + + public void setClientRequestId(String clientRequestId) { + this.clientRequestId = clientRequestId; + } + + public String getClientRequestId() { + if(clientRequestId == null) { + clientRequestId = UUID.randomUUID().toString(); + } + return clientRequestId; + } + +} diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index 85bb76fd5..6043c432d 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -4,6 +4,7 @@ import org.junit.Test; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -21,5 +22,18 @@ public Request authenticateRequest(Request request) { OkHttpClient httpclient = HttpClients.createDefault(authprovider); assertTrue(httpclient != null); } + + @Test + public void arrayInterceptorsTest() { + AuthenticationHandler authenticationHandler = new AuthenticationHandler(new ICoreAuthenticationProvider() { + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Interceptor[] interceptors = {new RetryHandler(), new RedirectHandler(), authenticationHandler}; + OkHttpClient client = HttpClients.createFromInterceptors(interceptors); + assertTrue(client.interceptors().size()==4); + } } diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java new file mode 100644 index 000000000..8f49b8126 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java @@ -0,0 +1,59 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.junit.Ignore; +import org.junit.Test; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +@Ignore +public class TelemetryHandlerTest { + @Test + public void telemetryInitTest() { + TelemetryHandler telemetryHandler = new TelemetryHandler(); + assertNotNull(telemetryHandler); + } + + @Test + public void interceptTest() throws IOException { + String expectedHeader = TelemetryHandler.SDK_VERSION + TelemetryHandler.GRAPH_VERSION_PREFIX +"/" + +TelemetryHandler.VERSION; + OkHttpClient client = HttpClients.createDefault(new ICoreAuthenticationProvider() { + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); + Response response = client.newCall(request).execute(); + assertNotNull(response); + assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); + } + + @Test + public void arrayInterceptorsTest() throws IOException { + + AuthenticationHandler authenticationHandler = new AuthenticationHandler(new ICoreAuthenticationProvider() { + + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Interceptor[] interceptors = {new RetryHandler(), new RedirectHandler(), authenticationHandler}; + OkHttpClient client = HttpClients.createFromInterceptors(interceptors); + String expectedHeader = TelemetryHandler.SDK_VERSION + TelemetryHandler.GRAPH_VERSION_PREFIX +"/" + +TelemetryHandler.VERSION; + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); + Response response = client.newCall(request).execute(); + assertNotNull(response); + assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); + } +} diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java new file mode 100644 index 000000000..dece2ef55 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java @@ -0,0 +1,53 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; + +public class TelemetryOptionsTest { + + @Test + public void createTelemetryOptionsTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + assertNotNull(telemetryOptions); + assertNotNull(telemetryOptions.getClientRequestId()); + } + + @Test + public void setFeatureUsageTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + assertTrue(telemetryOptions.getFeatureUsage().compareTo("5")==0); + } + + @Test + public void getFeatureUsageTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + assertTrue(telemetryOptions.getFeatureUsage().compareTo("7")==0); + } + + @Test + public void setClientRequestIdTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setClientRequestId("test id"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id")==0); + } + + @Test + public void getClientRequestIdTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + assertNotNull(telemetryOptions.getClientRequestId()); + telemetryOptions.setClientRequestId("test id 1"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id 1")==0); + telemetryOptions.setClientRequestId("test id 2"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id 2")==0); + } + +}