allowedQueryParamNames) {
+ this.allowedQueryParamNames
+ = allowedQueryParamNames == null ? new HashSet<>() : new HashSet<>(allowedQueryParamNames);
+
+ return this;
+ }
+
+ /**
+ * Sets the given allowed query param that can be recorded on logs and traces.
+ *
+ * @param allowedQueryParamName The allowed query param name from the user.
+ *
+ * @return The updated {@link HttpInstrumentationOptions} object.
+ *
+ * @throws NullPointerException If {@code allowedQueryParamName} is {@code null}.
+ */
+ public HttpInstrumentationOptions addAllowedQueryParamName(final String allowedQueryParamName) {
+ this.allowedQueryParamNames.add(allowedQueryParamName);
+ return this;
+ }
+
+ @Override
+ public HttpInstrumentationOptions setTracingEnabled(boolean isTracingEnabled) {
+ super.setTracingEnabled(isTracingEnabled);
+ return this;
+ }
+
+ @Override
+ public HttpInstrumentationOptions setTelemetryProvider(Object telemetryProvider) {
+ super.setTelemetryProvider(telemetryProvider);
+ return this;
+ }
+
+ /**
+ * The level of detail for HTTP request logs.
+ */
+ public enum HttpLogDetailLevel {
+ /**
+ * HTTP logging is turned off.
+ */
+ NONE,
+
+ /**
+ * Enables logging the following information on detailed HTTP logs
+ *
+ * - Request method, URI, and body size. URI is sanitized based on allowed query parameters configurable with {@link #setAllowedQueryParamNames(Set)} and {@link #addAllowedQueryParamName(String)}
+ * - Response status code and body size
+ * - Request and response headers from allow-list configured via {@link #setAllowedHeaderNames(Set)} and {@link #addAllowedHeaderName(HttpHeaderName)}.
+ * - Error details if the request fails
+ * - Time it takes to receive response
+ * - Correlation identifiers
+ *
+ */
+ HEADERS,
+
+ /**
+ * Enables logging the following information on detailed HTTP logs
+ *
+ * - Request method, URI, and body size. URI is sanitized based on allowed query parameters configurable with {@link #setAllowedQueryParamNames(Set)} and {@link #addAllowedQueryParamName(String)}
+ * - Response status code and body size
+ * - Error details if the request fails
+ * - Time it takes to receive response
+ * - Correlation identifiers
+ * - Request and response bodies
+ * - Time-to-last-byte
+ *
+ *
+ *
+ * The request and response body will be buffered into memory even if it is never consumed by an application, possibly impacting
+ * performance.
+ *
+ * Body is not logged (and not buffered) for requests and responses where the content length is not known or greater than 16KB.
+ */
+ BODY,
+
+ /**
+ * Enables logging everything in {@link #HEADERS} and {@link #BODY}.
+ *
+ *
+ * The request and response body will be buffered into memory even if it is never consumed by an application, possibly impacting
+ * performance.
+ *
+ * Body is not logged (and not buffered) for requests and responses where the content length is not known or greater than 16KB.
+ */
+ BODY_AND_HEADERS;
+
+ private static final String HEADERS_VALUE = "headers";
+ private static final String BODY_VALUE = "body";
+ private static final String BODY_AND_HEADERS_VALUE = "body_and_headers";
+
+ private static final ConfigurationProperty HTTP_LOG_DETAIL_LEVEL
+ = ConfigurationPropertyBuilder.ofString("http.log.detail.level")
+ .shared(true)
+ .environmentVariableName(Configuration.PROPERTY_HTTP_LOG_DETAIL_LEVEL)
+ .defaultValue("none")
+ .build();
+
+ static HttpLogDetailLevel fromConfiguration(Configuration configuration) {
+ String detailLevel = configuration.get(HTTP_LOG_DETAIL_LEVEL);
+
+ HttpLogDetailLevel logDetailLevel;
+
+ if (HEADERS_VALUE.equalsIgnoreCase(detailLevel)) {
+ logDetailLevel = HEADERS;
+ } else if (BODY_VALUE.equalsIgnoreCase(detailLevel)) {
+ logDetailLevel = BODY;
+ } else if (BODY_AND_HEADERS_VALUE.equalsIgnoreCase(detailLevel)) {
+ logDetailLevel = BODY_AND_HEADERS;
+ } else {
+ logDetailLevel = NONE;
+ }
+
+ return logDetailLevel;
+ }
+ }
+}
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/http/models/HttpLogOptions.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/http/models/HttpLogOptions.java
deleted file mode 100644
index 1814586f3779d..0000000000000
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/http/models/HttpLogOptions.java
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package io.clientcore.core.http.models;
-
-import io.clientcore.core.util.configuration.Configuration;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import static io.clientcore.core.util.configuration.Configuration.getGlobalConfiguration;
-
-/**
- * The log configurations for HTTP messages.
- */
-public final class HttpLogOptions {
- private HttpLogDetailLevel logLevel;
- private Set allowedHeaderNames;
- private Set allowedQueryParamNames;
- private static final List DEFAULT_HEADERS_ALLOWLIST
- = Arrays.asList(HttpHeaderName.TRACEPARENT, HttpHeaderName.ACCEPT, HttpHeaderName.CACHE_CONTROL,
- HttpHeaderName.CONNECTION, HttpHeaderName.CONTENT_LENGTH, HttpHeaderName.CONTENT_TYPE, HttpHeaderName.DATE,
- HttpHeaderName.ETAG, HttpHeaderName.EXPIRES, HttpHeaderName.IF_MATCH, HttpHeaderName.IF_MODIFIED_SINCE,
- HttpHeaderName.IF_NONE_MATCH, HttpHeaderName.IF_UNMODIFIED_SINCE, HttpHeaderName.LAST_MODIFIED,
- HttpHeaderName.PRAGMA, HttpHeaderName.RETRY_AFTER, HttpHeaderName.SERVER, HttpHeaderName.TRANSFER_ENCODING,
- HttpHeaderName.USER_AGENT, HttpHeaderName.WWW_AUTHENTICATE);
-
- private static final List DEFAULT_QUERY_PARAMS_ALLOWLIST = Collections.singletonList("api-version");
-
- /**
- * Creates a new instance that does not log any information about HTTP requests or responses.
- */
- public HttpLogOptions() {
- logLevel = HttpLogDetailLevel.ENVIRONMENT_HTTP_LOG_DETAIL_LEVEL;
- allowedHeaderNames = new HashSet<>(DEFAULT_HEADERS_ALLOWLIST);
- allowedQueryParamNames = new HashSet<>(DEFAULT_QUERY_PARAMS_ALLOWLIST);
- }
-
- /**
- * Gets the level of detail to log on HTTP messages.
- *
- * @return The {@link HttpLogDetailLevel}.
- */
- public HttpLogDetailLevel getLogLevel() {
- return logLevel;
- }
-
- /**
- * Sets the level of detail to log on Http messages.
- *
- * If logLevel is not provided, default value of {@link HttpLogDetailLevel#NONE} is set.
- *
- * @param logLevel The {@link HttpLogDetailLevel}.
- *
- * @return The updated HttpLogOptions object.
- */
- public HttpLogOptions setLogLevel(final HttpLogDetailLevel logLevel) {
- this.logLevel = logLevel == null ? HttpLogDetailLevel.NONE : logLevel;
-
- return this;
- }
-
- /**
- * Gets the allowed headers that should be logged.
- *
- * @return The list of allowed headers.
- */
- public Set getAllowedHeaderNames() {
- return Collections.unmodifiableSet(allowedHeaderNames);
- }
-
- /**
- * Sets the given allowed headers that should be logged.
- *
- *
- * This method sets the provided header names to be the allowed header names which will be logged for all HTTP
- * requests and responses, overwriting any previously configured headers. Additionally, users can use
- * {@link HttpLogOptions#addAllowedHeaderName(HttpHeaderName)} or {@link HttpLogOptions#getAllowedHeaderNames()} to add or
- * remove more headers names to the existing set of allowed header names.
- *
- *
- * @param allowedHeaderNames The list of allowed header names from the user.
- *
- * @return The updated HttpLogOptions object.
- */
- public HttpLogOptions setAllowedHeaderNames(final Set allowedHeaderNames) {
- this.allowedHeaderNames = allowedHeaderNames == null ? new HashSet<>() : allowedHeaderNames;
-
- return this;
- }
-
- /**
- * Sets the given allowed header to the default header set that should be logged.
- *
- * @param allowedHeaderName The allowed header name from the user.
- *
- * @return The updated HttpLogOptions object.
- *
- * @throws NullPointerException If {@code allowedHeaderName} is {@code null}.
- */
- public HttpLogOptions addAllowedHeaderName(final HttpHeaderName allowedHeaderName) {
- Objects.requireNonNull(allowedHeaderName);
- this.allowedHeaderNames.add(allowedHeaderName);
-
- return this;
- }
-
- /**
- * Gets the allowed query parameters.
- *
- * @return The list of allowed query parameters.
- */
- public Set getAllowedQueryParamNames() {
- return Collections.unmodifiableSet(allowedQueryParamNames);
- }
-
- /**
- * Sets the given allowed query params to be displayed in the logging info.
- *
- * @param allowedQueryParamNames The list of allowed query params from the user.
- *
- * @return The updated HttpLogOptions object.
- */
- public HttpLogOptions setAllowedQueryParamNames(final Set allowedQueryParamNames) {
- this.allowedQueryParamNames = allowedQueryParamNames == null ? new HashSet<>() : allowedQueryParamNames;
-
- return this;
- }
-
- /**
- * Sets the given allowed query param that should be logged.
- *
- * @param allowedQueryParamName The allowed query param name from the user.
- *
- * @return The updated HttpLogOptions object.
- *
- * @throws NullPointerException If {@code allowedQueryParamName} is {@code null}.
- */
- public HttpLogOptions addAllowedQueryParamName(final String allowedQueryParamName) {
- this.allowedQueryParamNames.add(allowedQueryParamName);
- return this;
- }
-
- /**
- * The level of detail to log on HTTP messages.
- */
- public enum HttpLogDetailLevel {
- /**
- * Logging is turned off.
- */
- NONE,
-
- /**
- * Logs only URIs, HTTP methods, and time to finish the request.
- */
- BASIC,
-
- /**
- * Logs everything in BASIC, plus all allowed request and response headers.
- */
- HEADERS,
-
- /**
- * Logs everything in BASIC, plus all the request and response body. Note that only payloads in plain text or
- * plain text encoded in GZIP will be logged.
- */
- BODY,
-
- /**
- * Logs everything in HEADERS and BODY.
- */
- BODY_AND_HEADERS;
-
- static final String BASIC_VALUE = "basic";
- static final String HEADERS_VALUE = "headers";
- static final String BODY_VALUE = "body";
- static final String BODY_AND_HEADERS_VALUE = "body_and_headers";
- static final String BODYANDHEADERS_VALUE = "bodyandheaders";
- static final HttpLogDetailLevel ENVIRONMENT_HTTP_LOG_DETAIL_LEVEL = fromConfiguration(getGlobalConfiguration());
-
- static HttpLogDetailLevel fromConfiguration(Configuration configuration) {
- String detailLevel = configuration.get(Configuration.PROPERTY_HTTP_LOG_DETAIL_LEVEL, "none");
-
- HttpLogDetailLevel logDetailLevel;
-
- if (BASIC_VALUE.equalsIgnoreCase(detailLevel)) {
- logDetailLevel = BASIC;
- } else if (HEADERS_VALUE.equalsIgnoreCase(detailLevel)) {
- logDetailLevel = HEADERS;
- } else if (BODY_VALUE.equalsIgnoreCase(detailLevel)) {
- logDetailLevel = BODY;
- } else if (BODY_AND_HEADERS_VALUE.equalsIgnoreCase(detailLevel)
- || BODYANDHEADERS_VALUE.equalsIgnoreCase(detailLevel)) {
-
- logDetailLevel = BODY_AND_HEADERS;
- } else {
- logDetailLevel = NONE;
- }
-
- return logDetailLevel;
- }
-
- /**
- * Whether a URI should be logged.
- *
- * @return Whether a URI should be logged.
- */
- public boolean shouldLogUri() {
- return this != NONE;
- }
-
- /**
- * Whether headers should be logged.
- *
- * @return Whether headers should be logged.
- */
- public boolean shouldLogHeaders() {
- return this == HEADERS || this == BODY_AND_HEADERS;
- }
-
- /**
- * Whether a body should be logged.
- *
- * @return Whether a body should be logged.
- */
- public boolean shouldLogBody() {
- return this == BODY || this == BODY_AND_HEADERS;
- }
- }
-}
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/http/pipeline/HttpInstrumentationPolicy.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/http/pipeline/HttpInstrumentationPolicy.java
index 679d30246ee7a..40f0d7e7ea4e0 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/http/pipeline/HttpInstrumentationPolicy.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/http/pipeline/HttpInstrumentationPolicy.java
@@ -6,7 +6,7 @@
import io.clientcore.core.http.models.HttpHeader;
import io.clientcore.core.http.models.HttpHeaderName;
import io.clientcore.core.http.models.HttpHeaders;
-import io.clientcore.core.http.models.HttpLogOptions;
+import io.clientcore.core.http.models.HttpInstrumentationOptions;
import io.clientcore.core.http.models.HttpRequest;
import io.clientcore.core.http.models.HttpResponse;
import io.clientcore.core.http.models.RequestOptions;
@@ -16,7 +16,6 @@
import io.clientcore.core.instrumentation.Instrumentation;
import io.clientcore.core.instrumentation.InstrumentationContext;
import io.clientcore.core.instrumentation.LibraryInstrumentationOptions;
-import io.clientcore.core.instrumentation.InstrumentationOptions;
import io.clientcore.core.instrumentation.tracing.SpanBuilder;
import io.clientcore.core.instrumentation.tracing.TracingScope;
import io.clientcore.core.instrumentation.tracing.Span;
@@ -69,7 +68,7 @@
* {@link HttpRetryPolicy} and {@link HttpRedirectPolicy} so that it's executed on each try or redirect and logging happens
* in the scope of the span.
*
- * The policy supports basic customizations using {@link InstrumentationOptions} and {@link HttpLogOptions}.
+ * The policy supports basic customizations using {@link HttpInstrumentationOptions}.
*
* If your client library needs a different approach to distributed tracing,
* you can create a custom policy and use it instead of the {@link HttpInstrumentationPolicy}. If you want to enrich instrumentation
@@ -83,7 +82,7 @@
* HttpPipeline pipeline = new HttpPipelineBuilder()
* .policies(
* new HttpRetryPolicy(),
- * new HttpInstrumentationPolicy(instrumentationOptions, logOptions))
+ * new HttpInstrumentationPolicy(instrumentationOptions))
* .build();
*
*
@@ -95,13 +94,13 @@
*
* // You can configure URL sanitization to include additional query parameters to preserve
* // in `url.full` attribute.
- * HttpLogOptions logOptions = new HttpLogOptions();
- * logOptions.addAllowedQueryParamName("documentId");
+ * HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions();
+ * instrumentationOptions.addAllowedQueryParamName("documentId");
*
* HttpPipeline pipeline = new HttpPipelineBuilder()
* .policies(
* new HttpRetryPolicy(),
- * new HttpInstrumentationPolicy(instrumentationOptions, logOptions))
+ * new HttpInstrumentationPolicy(instrumentationOptions))
* .build();
*
*
@@ -125,7 +124,7 @@
* HttpPipeline pipeline = new HttpPipelineBuilder()
* .policies(
* new HttpRetryPolicy(),
- * new HttpInstrumentationPolicy(instrumentationOptions, logOptions),
+ * new HttpInstrumentationPolicy(instrumentationOptions),
* enrichingPolicy)
* .build();
*
@@ -136,7 +135,7 @@
*/
public final class HttpInstrumentationPolicy implements HttpPipelinePolicy {
private static final ClientLogger LOGGER = new ClientLogger(HttpInstrumentationPolicy.class);
- private static final HttpLogOptions DEFAULT_LOG_OPTIONS = new HttpLogOptions();
+ private static final HttpInstrumentationOptions DEFAULT_OPTIONS = new HttpInstrumentationOptions();
private static final String LIBRARY_NAME;
private static final String LIBRARY_VERSION;
private static final LibraryInstrumentationOptions LIBRARY_OPTIONS;
@@ -170,23 +169,29 @@ public final class HttpInstrumentationPolicy implements HttpPipelinePolicy {
private final Tracer tracer;
private final TraceContextPropagator traceContextPropagator;
private final Set allowedQueryParameterNames;
- private final HttpLogOptions.HttpLogDetailLevel httpLogDetailLevel;
private final Set allowedHeaderNames;
+ private final boolean isLoggingEnabled;
+ private final boolean isContentLoggingEnabled;
+ private final boolean isRedactedHeadersLoggingEnabled;
/**
* Creates a new instrumentation policy.
* @param instrumentationOptions Application telemetry options.
- * @param logOptions Http log options. TODO: we should merge this with telemetry options.
*/
- public HttpInstrumentationPolicy(InstrumentationOptions> instrumentationOptions, HttpLogOptions logOptions) {
+ public HttpInstrumentationPolicy(HttpInstrumentationOptions instrumentationOptions) {
Instrumentation instrumentation = Instrumentation.create(instrumentationOptions, LIBRARY_OPTIONS);
this.tracer = instrumentation.getTracer();
this.traceContextPropagator = instrumentation.getW3CTraceContextPropagator();
- HttpLogOptions logOptionsToUse = logOptions == null ? DEFAULT_LOG_OPTIONS : logOptions;
- this.httpLogDetailLevel = logOptionsToUse.getLogLevel();
- this.allowedHeaderNames = logOptionsToUse.getAllowedHeaderNames();
- this.allowedQueryParameterNames = logOptionsToUse.getAllowedQueryParamNames()
+ HttpInstrumentationOptions optionsToUse
+ = instrumentationOptions == null ? DEFAULT_OPTIONS : instrumentationOptions;
+ this.isLoggingEnabled = optionsToUse.getHttpLogLevel() != HttpInstrumentationOptions.HttpLogDetailLevel.NONE;
+ this.isContentLoggingEnabled
+ = optionsToUse.getHttpLogLevel() == HttpInstrumentationOptions.HttpLogDetailLevel.BODY
+ || optionsToUse.getHttpLogLevel() == HttpInstrumentationOptions.HttpLogDetailLevel.BODY_AND_HEADERS;
+ this.isRedactedHeadersLoggingEnabled = optionsToUse.isRedactedHeaderNamesLoggingEnabled();
+ this.allowedHeaderNames = optionsToUse.getAllowedHeaderNames();
+ this.allowedQueryParameterNames = optionsToUse.getAllowedQueryParamNames()
.stream()
.map(queryParamName -> queryParamName.toLowerCase(Locale.ROOT))
.collect(Collectors.toSet());
@@ -199,7 +204,7 @@ public HttpInstrumentationPolicy(InstrumentationOptions> instrumentationOption
@Override
public Response> process(HttpRequest request, HttpPipelineNextPolicy next) {
boolean isTracingEnabled = tracer.isEnabled();
- if (!isTracingEnabled && httpLogDetailLevel == HttpLogOptions.HttpLogDetailLevel.NONE) {
+ if (!isTracingEnabled && !isLoggingEnabled) {
return next.process();
}
@@ -355,7 +360,7 @@ private static Map getProperties(String propertiesFileName) {
private void logRequest(ClientLogger logger, HttpRequest request, long startNanoTime, long requestContentLength,
String redactedUrl, int tryCount, InstrumentationContext context) {
ClientLogger.LoggingEvent logBuilder = logger.atLevel(HTTP_REQUEST_LOG_LEVEL);
- if (!logBuilder.isEnabled() || httpLogDetailLevel == HttpLogOptions.HttpLogDetailLevel.NONE) {
+ if (!logBuilder.isEnabled() || !isLoggingEnabled) {
return;
}
@@ -368,7 +373,7 @@ private void logRequest(ClientLogger logger, HttpRequest request, long startNano
addHeadersToLogMessage(request.getHeaders(), logBuilder);
- if (httpLogDetailLevel.shouldLogBody() && canLogBody(request.getBody())) {
+ if (isContentLoggingEnabled && canLogBody(request.getBody())) {
try {
BinaryData bufferedBody = request.getBody().toReplayableBinaryData();
request.setBody(bufferedBody);
@@ -386,7 +391,7 @@ private void logRequest(ClientLogger logger, HttpRequest request, long startNano
private Response> logResponse(ClientLogger logger, Response> response, long startNanoTime,
long requestContentLength, String redactedUrl, int tryCount, InstrumentationContext context) {
ClientLogger.LoggingEvent logBuilder = logger.atLevel(HTTP_RESPONSE_LOG_LEVEL);
- if (httpLogDetailLevel == HttpLogOptions.HttpLogDetailLevel.NONE) {
+ if (!isLoggingEnabled) {
return response;
}
@@ -408,7 +413,7 @@ private Response> logResponse(ClientLogger logger, Response> response, long
addHeadersToLogMessage(response.getHeaders(), logBuilder);
}
- if (httpLogDetailLevel.shouldLogBody() && canLogBody(response.getBody())) {
+ if (isContentLoggingEnabled && canLogBody(response.getBody())) {
return new LoggingHttpResponse<>(response, content -> {
if (logBuilder.isEnabled()) {
logBuilder.addKeyValue(HTTP_RESPONSE_BODY_CONTENT_KEY, content.toString())
@@ -431,7 +436,7 @@ private T logException(ClientLogger logger, HttpRequest re
int tryCount, InstrumentationContext context) {
ClientLogger.LoggingEvent log = logger.atLevel(ClientLogger.LogLevel.WARNING);
- if (!log.isEnabled() || httpLogDetailLevel == HttpLogOptions.HttpLogDetailLevel.NONE) {
+ if (!log.isEnabled() || !isLoggingEnabled) {
return throwable;
}
@@ -484,11 +489,12 @@ private static boolean canLogBody(BinaryData data) {
* @param logBuilder Log message builder.
*/
private void addHeadersToLogMessage(HttpHeaders headers, ClientLogger.LoggingEvent logBuilder) {
- if (httpLogDetailLevel.shouldLogHeaders()) {
- for (HttpHeader header : headers) {
- HttpHeaderName headerName = header.getName();
- String headerValue = allowedHeaderNames.contains(headerName) ? header.getValue() : REDACTED_PLACEHOLDER;
- logBuilder.addKeyValue(headerName.toString(), headerValue);
+ for (HttpHeader header : headers) {
+ HttpHeaderName headerName = header.getName();
+ if (allowedHeaderNames.contains(headerName)) {
+ logBuilder.addKeyValue(headerName.toString(), header.getValue());
+ } else if (isRedactedHeadersLoggingEnabled) {
+ logBuilder.addKeyValue(headerName.toString(), REDACTED_PLACEHOLDER);
}
}
}
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackInstrumentation.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackInstrumentation.java
index 109398c9efbd0..9c282c9eb380b 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackInstrumentation.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackInstrumentation.java
@@ -17,7 +17,7 @@
public class FallbackInstrumentation implements Instrumentation {
public static final FallbackInstrumentation DEFAULT_INSTANCE = new FallbackInstrumentation(null, null);
- private final InstrumentationOptions> instrumentationOptions;
+ private final InstrumentationOptions instrumentationOptions;
private final LibraryInstrumentationOptions libraryOptions;
/**
@@ -25,7 +25,7 @@ public class FallbackInstrumentation implements Instrumentation {
* @param instrumentationOptions the application instrumentation options
* @param libraryOptions the library instrumentation options
*/
- public FallbackInstrumentation(InstrumentationOptions> instrumentationOptions,
+ public FallbackInstrumentation(InstrumentationOptions instrumentationOptions,
LibraryInstrumentationOptions libraryOptions) {
this.instrumentationOptions = instrumentationOptions;
this.libraryOptions = libraryOptions;
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackTracer.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackTracer.java
index 006d86ebeacf2..15ac5def63ad6 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackTracer.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/fallback/FallbackTracer.java
@@ -19,15 +19,15 @@ final class FallbackTracer implements Tracer {
private final boolean isEnabled;
private final ClientLogger logger;
- FallbackTracer(InstrumentationOptions> instrumentationOptions, LibraryInstrumentationOptions libraryOptions) {
+ FallbackTracer(InstrumentationOptions instrumentationOptions, LibraryInstrumentationOptions libraryOptions) {
// TODO (limolkova): do we need additional config to enable fallback tracing? Or maybe we enable it only if logs are enabled?
this.isEnabled = instrumentationOptions == null || instrumentationOptions.isTracingEnabled();
this.logger = isEnabled ? getLogger(instrumentationOptions, libraryOptions) : LOGGER;
}
- private static ClientLogger getLogger(InstrumentationOptions> instrumentationOptions,
+ private static ClientLogger getLogger(InstrumentationOptions instrumentationOptions,
LibraryInstrumentationOptions libraryOptions) {
- Object providedLogger = instrumentationOptions == null ? null : instrumentationOptions.getProvider();
+ Object providedLogger = instrumentationOptions == null ? null : instrumentationOptions.getTelemetryProvider();
if (providedLogger instanceof ClientLogger) {
return (ClientLogger) providedLogger;
}
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/otel/OTelInstrumentation.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/otel/OTelInstrumentation.java
index 38783b3bf6bc4..1fcf5b29fa6c9 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/otel/OTelInstrumentation.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/implementation/instrumentation/otel/OTelInstrumentation.java
@@ -78,9 +78,9 @@ public class OTelInstrumentation implements Instrumentation {
* @param applicationOptions the application options
* @param libraryOptions the library options
*/
- public OTelInstrumentation(InstrumentationOptions> applicationOptions,
+ public OTelInstrumentation(InstrumentationOptions applicationOptions,
LibraryInstrumentationOptions libraryOptions) {
- Object explicitOTel = applicationOptions == null ? null : applicationOptions.getProvider();
+ Object explicitOTel = applicationOptions == null ? null : applicationOptions.getTelemetryProvider();
if (explicitOTel != null && !OTEL_CLASS.isInstance(explicitOTel)) {
throw LOGGER.atError()
.addKeyValue("expectedProvider", OTEL_CLASS.getName())
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/Instrumentation.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/Instrumentation.java
index c1de07959f73d..aefbdc64551ad 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/Instrumentation.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/Instrumentation.java
@@ -30,7 +30,7 @@ public interface Instrumentation {
* .setLibraryVersion("1.0.0")
* .setSchemaUrl("https://opentelemetry.io/schemas/1.29.0");
*
- * InstrumentationOptions<?> instrumentationOptions = new InstrumentationOptions<>();
+ * InstrumentationOptions instrumentationOptions = new InstrumentationOptions();
*
* Tracer tracer = Instrumentation.create(instrumentationOptions, libraryOptions).getTracer();
*
@@ -61,7 +61,7 @@ public interface Instrumentation {
* @param libraryOptions Library-specific telemetry collection options.
* @return The instance of telemetry provider implementation.
*/
- static Instrumentation create(InstrumentationOptions> applicationOptions,
+ static Instrumentation create(InstrumentationOptions applicationOptions,
LibraryInstrumentationOptions libraryOptions) {
Objects.requireNonNull(libraryOptions, "'libraryOptions' cannot be null");
if (OTelInitializer.isInitialized()) {
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/InstrumentationOptions.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/InstrumentationOptions.java
index 230f6068ce4ab..37a57a2fe0e09 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/InstrumentationOptions.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/InstrumentationOptions.java
@@ -13,12 +13,10 @@
* Library should use them on all instance of {@link io.clientcore.core.instrumentation.tracing.Tracer}
* it creates and, if it sets up {@link HttpInstrumentationPolicy}, it should pass
* {@link InstrumentationOptions} to the policy.
- *
- * @param The type of the provider. Only {@code io.opentelemetry.api.OpenTelemetry} is supported.
*/
-public class InstrumentationOptions {
+public class InstrumentationOptions {
private boolean isTracingEnabled = true;
- private T provider = null;
+ private Object telemetryProvider = null;
/**
* Enables or disables distributed tracing. Distributed tracing is enabled by default when
@@ -29,7 +27,7 @@ public class InstrumentationOptions {
*
*
*
- * InstrumentationOptions<?> instrumentationOptions = new InstrumentationOptions<>()
+ * HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions()
* .setTracingEnabled(false);
*
* SampleClient client = new SampleClientBuilder().instrumentationOptions(instrumentationOptions).build();
@@ -41,14 +39,14 @@ public class InstrumentationOptions {
* @param isTracingEnabled true to enable distributed tracing, false to disable.
* @return The updated {@link InstrumentationOptions} object.
*/
- public InstrumentationOptions setTracingEnabled(boolean isTracingEnabled) {
+ public InstrumentationOptions setTracingEnabled(boolean isTracingEnabled) {
this.isTracingEnabled = isTracingEnabled;
return this;
}
/**
- * Sets the provider to use for telemetry. Only {@code io.opentelemetry.api.OpenTelemetry} and
- * derived classes are supported.
+ * Sets the telemetry provider. Only {@code io.opentelemetry.api.OpenTelemetry} and
+ * derived classes are currently supported.
*
*
* When provider is not passed explicitly, clients will attempt to use global OpenTelemetry instance.
@@ -58,21 +56,23 @@ public InstrumentationOptions setTracingEnabled(boolean isTracingEnabled) {
*
*
*
- * OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
- * InstrumentationOptions<OpenTelemetry> instrumentationOptions = new InstrumentationOptions<OpenTelemetry>()
- * .setProvider(openTelemetry);
+ * OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
+ * HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions()
+ * .setTelemetryProvider(openTelemetry);
*
* SampleClient client = new SampleClientBuilder().instrumentationOptions(instrumentationOptions).build();
+ *
+ * // this call will be traced using OpenTelemetry SDK provided explicitly
* client.clientCall();
*
*
*
*
- * @param provider The provider to use for telemetry.
+ * @param telemetryProvider The provider to use for telemetry.
* @return The updated {@link InstrumentationOptions} object.
*/
- public InstrumentationOptions setProvider(T provider) {
- this.provider = provider;
+ public InstrumentationOptions setTelemetryProvider(Object telemetryProvider) {
+ this.telemetryProvider = telemetryProvider;
return this;
}
@@ -90,8 +90,8 @@ public boolean isTracingEnabled() {
*
* @return The telemetry provider instance.
*/
- public T getProvider() {
- return provider;
+ public Object getTelemetryProvider() {
+ return telemetryProvider;
}
/**
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/package-info.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/package-info.java
index 63fa95b9eba61..59391cb272a54 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/package-info.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/instrumentation/package-info.java
@@ -27,6 +27,8 @@
* AutoConfiguredOpenTelemetrySdk.initialize();
*
* SampleClient client = new SampleClientBuilder().build();
+ *
+ * // this call will be traced using OpenTelemetry SDK initialized globally
* client.clientCall();
*
*
@@ -40,11 +42,13 @@
*
*
*
- * OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
- * InstrumentationOptions<OpenTelemetry> instrumentationOptions = new InstrumentationOptions<OpenTelemetry>()
- * .setProvider(openTelemetry);
+ * OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
+ * HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions()
+ * .setTelemetryProvider(openTelemetry);
*
* SampleClient client = new SampleClientBuilder().instrumentationOptions(instrumentationOptions).build();
+ *
+ * // this call will be traced using OpenTelemetry SDK provided explicitly
* client.clientCall();
*
*
diff --git a/sdk/clientcore/core/src/main/java/io/clientcore/core/models/traits/HttpTrait.java b/sdk/clientcore/core/src/main/java/io/clientcore/core/models/traits/HttpTrait.java
index b18fd73229f54..045a42a7c9ea9 100644
--- a/sdk/clientcore/core/src/main/java/io/clientcore/core/models/traits/HttpTrait.java
+++ b/sdk/clientcore/core/src/main/java/io/clientcore/core/models/traits/HttpTrait.java
@@ -4,7 +4,7 @@
package io.clientcore.core.models.traits;
import io.clientcore.core.http.client.HttpClient;
-import io.clientcore.core.http.models.HttpLogOptions;
+import io.clientcore.core.http.models.HttpInstrumentationOptions;
import io.clientcore.core.http.models.HttpRedirectOptions;
import io.clientcore.core.http.models.HttpRetryOptions;
import io.clientcore.core.http.pipeline.HttpPipeline;
@@ -30,7 +30,7 @@
* @see HttpClient
* @see HttpPipeline
* @see HttpPipelinePolicy
- * @see HttpLogOptions
+ * @see HttpInstrumentationOptions
* @see HttpRetryOptions
* @see HttpRedirectOptions
*/
@@ -106,9 +106,21 @@ public interface HttpTrait> {
T httpRetryOptions(HttpRetryOptions retryOptions);
/**
- * Sets the {@link HttpLogOptions logging configuration} to use when sending and receiving requests to and from the
- * service. If a {@code logLevel} is not provided, default value of {@link HttpLogOptions.HttpLogDetailLevel#NONE}
- * is set.
+ * Sets the {@link HttpInstrumentationOptions instrumentation configuration} to use when recording telemetry about HTTP
+ * requests sent to the service and responses received from it.
+ *
+ * By default, when instrumentation options are not provided (explicitly or via environment variables), the following
+ * defaults are used:
+ *
+ * - Detailed HTTP logging about requests and responses is disabled
+ * - Distributed tracing is enabled. If OpenTelemetry is found on the classpath, HTTP requests are
+ * captured as OpenTelemetry spans.
+ * If OpenTelemetry is not found on the classpath, the same information is captured in logs.
+ * HTTP request spans contain basic information about the request, such as the HTTP method, URL, status code and
+ * duration.
+ * See {@link io.clientcore.core.http.pipeline.HttpInstrumentationPolicy} for
+ * the details.
+ *
*
* Note: It is important to understand the precedence order of the {@link HttpTrait} APIs. In
* particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
@@ -117,13 +129,13 @@ public interface HttpTrait> {
* trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
* documentation of types that implement this trait to understand the full set of implications.
*
- * @param logOptions The {@link HttpLogOptions logging configuration} to use when sending and receiving requests to
- * and from the service.
+ * @param instrumentationOptions The {@link HttpInstrumentationOptions configuration} to use when recording telemetry about HTTP
+ * requests sent to the service and responses received from it.
*
* @return Returns the same concrete type with the appropriate properties updated, to allow for fluent chaining of
* operations.
*/
- T httpLogOptions(HttpLogOptions logOptions);
+ T httpInstrumentationOptions(HttpInstrumentationOptions instrumentationOptions);
/**
* Sets the {@link HttpRedirectOptions} for all the requests made through the client.
diff --git a/sdk/clientcore/core/src/main/resources/META-INF/native-image.io.clientcore.core/native-image.properties b/sdk/clientcore/core/src/main/resources/META-INF/native-image.io.clientcore.core/native-image.properties
index 2298920b76204..e037782549eeb 100644
--- a/sdk/clientcore/core/src/main/resources/META-INF/native-image.io.clientcore.core/native-image.properties
+++ b/sdk/clientcore/core/src/main/resources/META-INF/native-image.io.clientcore.core/native-image.properties
@@ -17,10 +17,10 @@ Args=\
org.slf4j.MDC,\
org.slf4j.LoggerFactory,\
org.slf4j.impl.StaticLoggerBinder,\
- io.clientcore.core.util.ClientLogger.LogLevel,\
io.clientcore.core.util.Configuration,\
io.clientcore.core.util.implementation.ImplUtils,\
- io.clientcore.core.util.ClientLogger.LoggingEvent,\
+ io.clientcore.core.instrumentation.logging.ClientLogger.LogLevel,\
+ io.clientcore.core.instrumentation.logging.ClientLogger.LoggingEvent,\
diff --git a/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TelemetryJavaDocCodeSnippets.java b/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TelemetryJavaDocCodeSnippets.java
index 11779e0bbf1ba..7778f3b097e33 100644
--- a/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TelemetryJavaDocCodeSnippets.java
+++ b/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TelemetryJavaDocCodeSnippets.java
@@ -3,6 +3,7 @@
package io.clientcore.core.instrumentation;
+import io.clientcore.core.http.models.HttpInstrumentationOptions;
import io.clientcore.core.http.models.HttpMethod;
import io.clientcore.core.http.models.HttpRequest;
import io.clientcore.core.http.models.RequestOptions;
@@ -59,8 +60,8 @@ public void useCustomLogger() {
ClientLogger logger = new ClientLogger("sample-client-traces");
- InstrumentationOptions instrumentationOptions = new InstrumentationOptions()
- .setProvider(logger);
+ HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions()
+ .setTelemetryProvider(logger);
SampleClient client = new SampleClientBuilder().instrumentationOptions(instrumentationOptions).build();
client.clientCall();
@@ -75,7 +76,7 @@ public void useCustomLogger() {
public void disableDistributedTracing() {
// BEGIN: io.clientcore.core.telemetry.fallback.disabledistributedtracing
- InstrumentationOptions> instrumentationOptions = new InstrumentationOptions<>()
+ HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions()
.setTracingEnabled(false);
SampleClient client = new SampleClientBuilder().instrumentationOptions(instrumentationOptions).build();
@@ -137,16 +138,15 @@ public Span getSpan() {
}
static class SampleClientBuilder {
- private InstrumentationOptions> instrumentationOptions;
- // TODO (limolkova): do we need InstrumnetationTrait?
- public SampleClientBuilder instrumentationOptions(InstrumentationOptions> instrumentationOptions) {
+ private HttpInstrumentationOptions instrumentationOptions;
+ public SampleClientBuilder instrumentationOptions(HttpInstrumentationOptions instrumentationOptions) {
this.instrumentationOptions = instrumentationOptions;
return this;
}
public SampleClient build() {
return new SampleClient(instrumentationOptions, new HttpPipelineBuilder()
- .policies(new HttpInstrumentationPolicy(instrumentationOptions, null))
+ .policies(new HttpInstrumentationPolicy(instrumentationOptions))
.build());
}
}
@@ -156,7 +156,7 @@ static class SampleClient {
private final HttpPipeline httpPipeline;
private final io.clientcore.core.instrumentation.tracing.Tracer tracer;
- SampleClient(InstrumentationOptions> instrumentationOptions, HttpPipeline httpPipeline) {
+ SampleClient(InstrumentationOptions instrumentationOptions, HttpPipeline httpPipeline) {
this.httpPipeline = httpPipeline;
this.tracer = Instrumentation.create(instrumentationOptions, LIBRARY_OPTIONS).getTracer();
}
diff --git a/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TracingForLibraryDevelopersJavaDocCodeSnippets.java b/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TracingForLibraryDevelopersJavaDocCodeSnippets.java
index 5d294a02fa726..637e2c5d55a57 100644
--- a/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TracingForLibraryDevelopersJavaDocCodeSnippets.java
+++ b/sdk/clientcore/core/src/samples/java/io/clientcore/core/instrumentation/TracingForLibraryDevelopersJavaDocCodeSnippets.java
@@ -4,7 +4,7 @@
package io.clientcore.core.instrumentation;
import io.clientcore.core.http.models.HttpHeaderName;
-import io.clientcore.core.http.models.HttpLogOptions;
+import io.clientcore.core.http.models.HttpInstrumentationOptions;
import io.clientcore.core.http.models.RequestOptions;
import io.clientcore.core.http.pipeline.HttpInstrumentationPolicy;
import io.clientcore.core.http.pipeline.HttpPipeline;
@@ -37,7 +37,7 @@ public void createTracer() {
.setLibraryVersion("1.0.0")
.setSchemaUrl("https://opentelemetry.io/schemas/1.29.0");
- InstrumentationOptions> instrumentationOptions = new InstrumentationOptions<>();
+ InstrumentationOptions instrumentationOptions = new InstrumentationOptions();
Tracer tracer = Instrumentation.create(instrumentationOptions, libraryOptions).getTracer();
@@ -117,42 +117,38 @@ public void traceWithAttributes() {
}
public void configureInstrumentationPolicy() {
- InstrumentationOptions> instrumentationOptions = new InstrumentationOptions<>();
- HttpLogOptions logOptions = new HttpLogOptions();
+ HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions();
// BEGIN: io.clientcore.core.telemetry.tracing.instrumentationpolicy
HttpPipeline pipeline = new HttpPipelineBuilder()
.policies(
new HttpRetryPolicy(),
- new HttpInstrumentationPolicy(instrumentationOptions, logOptions))
+ new HttpInstrumentationPolicy(instrumentationOptions))
.build();
// END: io.clientcore.core.telemetry.tracing.instrumentationpolicy
}
public void customizeInstrumentationPolicy() {
- InstrumentationOptions> instrumentationOptions = new InstrumentationOptions<>();
-
// BEGIN: io.clientcore.core.telemetry.tracing.customizeinstrumentationpolicy
// You can configure URL sanitization to include additional query parameters to preserve
// in `url.full` attribute.
- HttpLogOptions logOptions = new HttpLogOptions();
- logOptions.addAllowedQueryParamName("documentId");
+ HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions();
+ instrumentationOptions.addAllowedQueryParamName("documentId");
HttpPipeline pipeline = new HttpPipelineBuilder()
.policies(
new HttpRetryPolicy(),
- new HttpInstrumentationPolicy(instrumentationOptions, logOptions))
+ new HttpInstrumentationPolicy(instrumentationOptions))
.build();
// END: io.clientcore.core.telemetry.tracing.customizeinstrumentationpolicy
}
public void enrichInstrumentationPolicySpans() {
- InstrumentationOptions> instrumentationOptions = new InstrumentationOptions<>();
- HttpLogOptions logOptions = new HttpLogOptions();
+ HttpInstrumentationOptions instrumentationOptions = new HttpInstrumentationOptions();
// BEGIN: io.clientcore.core.telemetry.tracing.enrichhttpspans
@@ -170,7 +166,7 @@ public void enrichInstrumentationPolicySpans() {
HttpPipeline pipeline = new HttpPipelineBuilder()
.policies(
new HttpRetryPolicy(),
- new HttpInstrumentationPolicy(instrumentationOptions, logOptions),
+ new HttpInstrumentationPolicy(instrumentationOptions),
enrichingPolicy)
.build();
diff --git a/sdk/clientcore/core/src/test/java/io/clientcore/core/http/pipeline/HttpInstrumentationLoggingTests.java b/sdk/clientcore/core/src/test/java/io/clientcore/core/http/pipeline/HttpInstrumentationLoggingTests.java
index f66fbf73974c0..456dd76bcccc2 100644
--- a/sdk/clientcore/core/src/test/java/io/clientcore/core/http/pipeline/HttpInstrumentationLoggingTests.java
+++ b/sdk/clientcore/core/src/test/java/io/clientcore/core/http/pipeline/HttpInstrumentationLoggingTests.java
@@ -7,7 +7,7 @@
import io.clientcore.core.http.models.HttpHeader;
import io.clientcore.core.http.models.HttpHeaderName;
import io.clientcore.core.http.models.HttpHeaders;
-import io.clientcore.core.http.models.HttpLogOptions;
+import io.clientcore.core.http.models.HttpInstrumentationOptions;
import io.clientcore.core.http.models.HttpMethod;
import io.clientcore.core.http.models.HttpRequest;
import io.clientcore.core.http.models.HttpRetryOptions;
@@ -16,7 +16,6 @@
import io.clientcore.core.implementation.AccessibleByteArrayOutputStream;
import io.clientcore.core.implementation.http.HttpRequestAccessHelper;
import io.clientcore.core.instrumentation.InstrumentationContext;
-import io.clientcore.core.instrumentation.InstrumentationOptions;
import io.clientcore.core.instrumentation.logging.ClientLogger;
import io.clientcore.core.util.binarydata.BinaryData;
import org.junit.jupiter.api.Test;
@@ -56,10 +55,11 @@
public class HttpInstrumentationLoggingTests {
private static final String URI = "https://example.com?param=value&api-version=42";
private static final String REDACTED_URI = "https://example.com?param=REDACTED&api-version=42";
- private static final Set DEFAULT_ALLOWED_QUERY_PARAMS = new HttpLogOptions().getAllowedQueryParamNames();
- private static final Set DEFAULT_ALLOWED_HEADERS = new HttpLogOptions().getAllowedHeaderNames();
+ private static final Set DEFAULT_ALLOWED_QUERY_PARAMS
+ = new HttpInstrumentationOptions().getAllowedQueryParamNames();
+ private static final Set DEFAULT_ALLOWED_HEADERS
+ = new HttpInstrumentationOptions().getAllowedHeaderNames();
private static final HttpHeaderName CUSTOM_REQUEST_ID = HttpHeaderName.fromString("custom-request-id");
- private static final InstrumentationOptions> DEFAULT_INSTRUMENTATION_OPTIONS = null;
private final AccessibleByteArrayOutputStream logCaptureStream;
@@ -69,12 +69,11 @@ public HttpInstrumentationLoggingTests() {
@ParameterizedTest
@MethodSource("disabledHttpLoggingSource")
- public void testDisabledHttpLogging(ClientLogger.LogLevel logLevel, HttpLogOptions.HttpLogDetailLevel httpLogLevel)
- throws IOException {
+ public void testDisabledHttpLogging(ClientLogger.LogLevel logLevel,
+ HttpInstrumentationOptions.HttpLogDetailLevel detailLevel) throws IOException {
ClientLogger logger = setupLogLevelAndGetLogger(logLevel, logCaptureStream);
- HttpPipeline pipeline
- = createPipeline(DEFAULT_INSTRUMENTATION_OPTIONS, new HttpLogOptions().setLogLevel(httpLogLevel));
+ HttpPipeline pipeline = createPipeline(new HttpInstrumentationOptions().setHttpLogLevel(detailLevel));
HttpRequest request = new HttpRequest(HttpMethod.GET, URI);
request.setRequestOptions(new RequestOptions().setLogger(logger));
@@ -84,21 +83,22 @@ public void testDisabledHttpLogging(ClientLogger.LogLevel logLevel, HttpLogOptio
}
public static Stream disabledHttpLoggingSource() {
- return Stream.of(Arguments.of(ClientLogger.LogLevel.VERBOSE, HttpLogOptions.HttpLogDetailLevel.NONE),
- Arguments.of(ClientLogger.LogLevel.WARNING, HttpLogOptions.HttpLogDetailLevel.BASIC),
- Arguments.of(ClientLogger.LogLevel.WARNING, HttpLogOptions.HttpLogDetailLevel.HEADERS),
- Arguments.of(ClientLogger.LogLevel.WARNING, HttpLogOptions.HttpLogDetailLevel.BODY),
- Arguments.of(ClientLogger.LogLevel.WARNING, HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS));
+ return Stream.of(
+ Arguments.of(ClientLogger.LogLevel.VERBOSE, HttpInstrumentationOptions.HttpLogDetailLevel.NONE),
+ Arguments.of(ClientLogger.LogLevel.WARNING, HttpInstrumentationOptions.HttpLogDetailLevel.HEADERS),
+ Arguments.of(ClientLogger.LogLevel.WARNING, HttpInstrumentationOptions.HttpLogDetailLevel.BODY), Arguments
+ .of(ClientLogger.LogLevel.WARNING, HttpInstrumentationOptions.HttpLogDetailLevel.BODY_AND_HEADERS));
}
@ParameterizedTest
@MethodSource("allowQueryParamSource")
public void testBasicHttpLogging(Set allowedParams, String expectedUri) throws IOException {
ClientLogger logger = setupLogLevelAndGetLogger(ClientLogger.LogLevel.VERBOSE, logCaptureStream);
- HttpLogOptions options = new HttpLogOptions().setLogLevel(HttpLogOptions.HttpLogDetailLevel.BASIC)
- .setAllowedQueryParamNames(allowedParams);
+ HttpInstrumentationOptions options
+ = new HttpInstrumentationOptions().setHttpLogLevel(HttpInstrumentationOptions.HttpLogDetailLevel.HEADERS)
+ .setAllowedQueryParamNames(allowedParams);
- HttpPipeline pipeline = createPipeline(DEFAULT_INSTRUMENTATION_OPTIONS, options);
+ HttpPipeline pipeline = createPipeline(options);
HttpRequest request = createRequest(HttpMethod.GET, URI, logger);
Response> response = pipeline.send(request);
@@ -108,19 +108,51 @@ public void testBasicHttpLogging(Set allowedParams, String expectedUri)
assertEquals(2, logMessages.size());
assertRequestLog(logMessages.get(0), expectedUri, request, null, 0);
- assertEquals(7, logMessages.get(0).size());
+ assertEquals(10, logMessages.get(0).size());
+ assertEquals("REDACTED", logMessages.get(0).get("Authorization"));
+ assertEquals("application/json", logMessages.get(0).get("Content-Type"));
assertResponseLog(logMessages.get(1), expectedUri, response, 0);
- assertEquals(11, logMessages.get(1).size());
+ assertEquals(14, logMessages.get(1).size());
+ assertEquals("13", logMessages.get(1).get("Content-Length"));
+ assertEquals("application/text", logMessages.get(1).get("Content-Type"));
+ assertEquals("REDACTED", logMessages.get(1).get("not-safe-to-log"));
+ }
+
+ @Test
+ public void testBasicHttpLoggingNoRedactedHeaders() throws IOException {
+ ClientLogger logger = setupLogLevelAndGetLogger(ClientLogger.LogLevel.VERBOSE, logCaptureStream);
+ HttpInstrumentationOptions options
+ = new HttpInstrumentationOptions().setHttpLogLevel(HttpInstrumentationOptions.HttpLogDetailLevel.HEADERS)
+ .setRedactedHeaderNamesLoggingEnabled(false);
+
+ HttpPipeline pipeline = createPipeline(options);
+
+ HttpRequest request = createRequest(HttpMethod.GET, URI, logger);
+ Response> response = pipeline.send(request);
+ response.close();
+
+ List