Skip to content

Commit

Permalink
Updated LoggingFactory to also log request HTTP method, URL, and head…
Browse files Browse the repository at this point in the history
…ers (Azure#394)

* Updated LoggingFactory to also log request HTTP method, URL, and headers
  • Loading branch information
seanmcc-msft authored and rickle-msft committed Oct 31, 2018
1 parent 988fd70 commit f311f6d
Show file tree
Hide file tree
Showing 6 changed files with 400 additions and 57 deletions.
1 change: 1 addition & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Removed internal dependency on javafx to be compatible with openjdk.
* Fixed a bug that would cause downloading large files with the TransferManager to fail.
* Fixed a bug in BlobURL.download() logic for setting up reliable download. This had the potential to download the wrong range when a download stream was retried.
* Added request Http Method, URL, and headers to logging messages.

2018.09.11 Version 10.1.0
* Interfaces for helper types updated to be more consistent throughout the library. All types, with the exception of the options for pipeline factories, use a fluent pattern.
Expand Down
101 changes: 101 additions & 0 deletions src/main/java/com/microsoft/azure/storage/blob/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ final class Constants {
* The query parameter for snapshots.
*/
static final String SNAPSHOT_QUERY_PARAMETER = "snapshot";
/**
* The word redacted.
*/
static final String REDACTED = "REDACTED";
/**
* The default amount of parallelism for TransferManager operations.
*/
Expand Down Expand Up @@ -152,6 +156,16 @@ static final class HeaderConstants {
*/
static final String RANGE_HEADER_FORMAT = "bytes=%d-%d";

/**
* The copy source header.
*/
static final String COPY_SOURCE = "x-ms-copy-source";

/**
* The version header.
*/
static final String VERSION = "x-ms-version";

/**
* The current storage version header value.
*/
Expand All @@ -176,4 +190,91 @@ private HeaderConstants() {
// Private to prevent construction.
}
}

static final class UrlConstants {

/**
* The SAS service version parameter.
*/
static final String SAS_SERVICE_VERSION = "sv";

/**
* The SAS services parameter.
*/
static final String SAS_SERVICES = "ss";

/**
* The SAS resource types parameter.
*/
static final String SAS_RESOURCES_TYPES = "srt";

/**
* The SAS protocol parameter.
*/
static final String SAS_PROTOCOL = "spr";

/**
* The SAS start time parameter.
*/
static final String SAS_START_TIME = "st";

/**
* The SAS expiration time parameter.
*/
static final String SAS_EXPIRY_TIME = "se";

/**
* The SAS IP range parameter.
*/
static final String SAS_IP_RANGE = "sip";

/**
* The SAS signed identifier parameter.
*/
static final String SAS_SIGNED_IDENTIFIER = "si";

/**
* The SAS signed resource parameter.
*/
static final String SAS_SIGNED_RESOURCE = "sr";

/**
* The SAS signed permissions parameter.
*/
static final String SAS_SIGNED_PERMISSIONS = "sp";

/**
* The SAS signature parameter.
*/
static final String SAS_SIGNATURE = "sig";

/**
* The SAS cache control parameter.
*/
static final String SAS_CACHE_CONTROL = "rscc";

/**
* The SAS content disposition parameter.
*/
static final String SAS_CONTENT_DISPOSITION = "rscd";

/**
* The SAS content encoding parameter.
*/
static final String SAS_CONTENT_ENCODING = "rsce";

/**
* The SAS content language parameter.
*/
static final String SAS_CONTENT_LANGUAGE = "rscl";

/**
* The SAS content type parameter.
*/
static final String SAS_CONTENT_TYPE = "rsct";

private UrlConstants() {
// Private to prevent construction.
}
}
}
84 changes: 82 additions & 2 deletions src/main/java/com/microsoft/azure/storage/blob/LoggingFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import io.reactivex.Single;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Locale;

/**
Expand Down Expand Up @@ -164,12 +167,89 @@ public Single<HttpResponse> sendAsync(final HttpRequest request) {
}

if (options.shouldLog(currentLevel)) {
String additionalMessageInfo = buildAdditionalMessageInfo(request);
String messageInfo = String.format(Locale.ROOT,
"Request try:'%d', request duration:'%d' ms, operation duration:'%d' ms%n",
tryCount, requestCompletionTime, operationDuration);
"Request try:'%d', request duration:'%d' ms, operation duration:'%d' ms%n%s",
tryCount, requestCompletionTime, operationDuration, additionalMessageInfo);
options.log(currentLevel, logMessage + messageInfo);
}
});
}

private String buildAdditionalMessageInfo(final HttpRequest httpRequest) {
HttpRequest sanitizedRequest = buildSanitizedRequest(httpRequest);
StringBuilder stringBuilder = new StringBuilder();
String format = "%s: %s" + System.lineSeparator();
stringBuilder.append(String.format(format, sanitizedRequest.httpMethod().toString(), sanitizedRequest.url().toString()));
sanitizedRequest.headers().forEach((header) -> stringBuilder.append(String.format(format, header.name(), header.value())));
return stringBuilder.toString();
}

private HttpRequest buildSanitizedRequest(final HttpRequest initialRequest) {
// Build new URL and redact SAS signature, if present
URL url = sanitizeURL(initialRequest.url());

// Build resultRequest
HttpRequest resultRequest = new HttpRequest(
initialRequest.callerMethod(),
initialRequest.httpMethod(),
url,
initialRequest.headers(),
initialRequest.body(),
initialRequest.responseDecoder());

// Redact Authorization header, if present
if(resultRequest.headers().value(Constants.HeaderConstants.AUTHORIZATION) != null) {
resultRequest.headers().set(Constants.HeaderConstants.AUTHORIZATION, Constants.REDACTED);
}

// Redact Copy Source header SAS signature, if present
if(resultRequest.headers().value(Constants.HeaderConstants.COPY_SOURCE) != null) {
try {
URL copySourceUrl = sanitizeURL(new URL(resultRequest.headers().value(Constants.HeaderConstants.COPY_SOURCE)));
resultRequest.headers().set(Constants.HeaderConstants.COPY_SOURCE, copySourceUrl.toString());
} catch(MalformedURLException e) {
throw new RuntimeException(e);
}
}

return resultRequest;
}

private URL sanitizeURL(URL initialURL) {
String urlString = initialURL.toString();
URL resultURL = initialURL;
try {
BlobURLParts urlParts = URLParser.parse(initialURL);
if(urlParts.sasQueryParameters() == null || urlParts.sasQueryParameters().signature() == null) {
return resultURL;
}
urlParts.withSasQueryParameters(new SASQueryParameters(
urlParts.sasQueryParameters().version(),
urlParts.sasQueryParameters().services(),
urlParts.sasQueryParameters().resourceTypes(),
urlParts.sasQueryParameters().protocol(),
urlParts.sasQueryParameters().startTime(),
urlParts.sasQueryParameters().expiryTime(),
urlParts.sasQueryParameters().ipRange(),
urlParts.sasQueryParameters().identifier(),
urlParts.sasQueryParameters().resource(),
urlParts.sasQueryParameters().permissions(),
Constants.REDACTED,
urlParts.sasQueryParameters().cacheControl(),
urlParts.sasQueryParameters().contentDisposition(),
urlParts.sasQueryParameters().contentEncoding(),
urlParts.sasQueryParameters().contentLanguage(),
urlParts.sasQueryParameters().contentType()
));
resultURL = urlParts.toURL();

/* We are only making valid changes to what has already been validated as a URL (since we got it from a URL object),
so there should be no need for either us or the caller to check this error. */
} catch(UnknownHostException | MalformedURLException e) {
throw new RuntimeException(e);
}
return resultURL;
}
}
}
Loading

0 comments on commit f311f6d

Please sign in to comment.