Skip to content

Commit

Permalink
Incorporate HTTP logging in the PowerShell
Browse files Browse the repository at this point in the history
  • Loading branch information
ogail authored and ogail committed Sep 25, 2013
1 parent e47a9e2 commit b0e1c1a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 40 deletions.
Expand Up @@ -527,15 +527,21 @@ out serviceName

ManagementClient = CloudContext.Clients.CreateManagementClient(
new CertificateCloudCredentials(subscription.SubscriptionId, subscription.Certificate),
new Uri(subscription.ServiceEndpoint)).WithHandler(new StandardHeadersHandler());
new Uri(subscription.ServiceEndpoint))
.WithHandler(new StandardHeadersHandler())
.WithHandler(new HttpRestCallLogger());

StorageClient = CloudContext.Clients.CreateStorageManagementClient(
new CertificateCloudCredentials(subscription.SubscriptionId, subscription.Certificate),
new Uri(subscription.ServiceEndpoint)).WithHandler(new StandardHeadersHandler());
new Uri(subscription.ServiceEndpoint))
.WithHandler(new StandardHeadersHandler())
.WithHandler(new HttpRestCallLogger());

ComputeClient = CloudContext.Clients.CreateComputeManagementClient(
new CertificateCloudCredentials(subscription.SubscriptionId, subscription.Certificate),
new Uri(subscription.ServiceEndpoint)).WithHandler(new StandardHeadersHandler());
new Uri(subscription.ServiceEndpoint))
.WithHandler(new StandardHeadersHandler())
.WithHandler(new HttpRestCallLogger());
}

internal CloudServiceClient(
Expand Down
Expand Up @@ -259,6 +259,7 @@
<Compile Include="Common\CmdletWithSubscriptionBase.cs" />
<Compile Include="Common\HttpClientExtensions.cs" />
<Compile Include="Common\HttpClientHelper.cs" />
<Compile Include="Common\HttpRestCallLogger.cs" />
<Compile Include="Common\ObjectDeltaMapper.cs" />
<Compile Include="Common\PowerShellUtility.cs" />
<Compile Include="Common\ServiceManagementClientExtensions.cs" />
Expand Down
Expand Up @@ -147,21 +147,10 @@ protected virtual void OnProcessRecord()

protected override void ProcessRecord()
{
try
{
Validate.ValidateInternetConnection();
InitChannelCurrentSubscription();
ExecuteCmdlet();
OnProcessRecord();
}
catch (CommunicationException ex)
{
WriteErrorDetails(ex);
}
catch (Exception ex)
{
WriteExceptionError(ex);
}
Validate.ValidateInternetConnection();
InitChannelCurrentSubscription();
base.ProcessRecord();
OnProcessRecord();
}

/// <summary>
Expand Down
Expand Up @@ -98,6 +98,7 @@ protected override void ProcessRecord()
{
WriteExceptionError(ex);
}
finally { WriteDebug(HttpRestCallLogger.Flush()); }
}

/// <summary>
Expand Down
83 changes: 64 additions & 19 deletions WindowsAzurePowershell/src/Commands.Utilities/Common/General.cs
Expand Up @@ -36,6 +36,7 @@ namespace Microsoft.WindowsAzure.Commands.Utilities.Common
using System.Xml.Serialization;
using XmlSchema.ServiceConfigurationSchema;
using JsonFormatting = Newtonsoft.Json.Formatting;
using System.Net.Http;

public static class General
{
Expand Down Expand Up @@ -777,6 +778,43 @@ public static string GetHttpRequestLog(string method, string requestUri, HttpHea
return GetHttpRequestLog(method, requestUri, ConvertHttpHeadersToWebHeaderCollection(headers), body);
}

public static string GetLog(HttpResponseMessage response)
{
string body = response.Content == null ? string.Empty : FormatString(response.Content.ReadAsStringAsync().Result);

return GetHttpResponseLog(
response.StatusCode.ToString(),
response.Headers,
body);
}

public static string GetLog(HttpRequestMessage request)
{
string body = request.Content == null ? string.Empty : FormatString(request.Content.ReadAsStringAsync().Result);

return GetHttpRequestLog(
request.Method.ToString(),
request.RequestUri.ToString(),
(HttpHeaders)request.Headers,
body);
}

public static string FormatString(string content)
{
if (IsXml(content))
{
return TryFormatXml(content);
}
else if (IsJson(content))
{
return General.TryFormatJson(content);
}
else
{
return content;
}
}

private static WebHeaderCollection ConvertHttpHeadersToWebHeaderCollection(HttpHeaders headers)
{
WebHeaderCollection webHeaders = new WebHeaderCollection();
Expand Down Expand Up @@ -804,21 +842,6 @@ private static string MessageHeadersToString(WebHeaderCollection headers)
return result.ToString();
}

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
public static string TryFormatJson(string str)
{
try
{
object parsedJson = JsonConvert.DeserializeObject(str);
return JsonConvert.SerializeObject(parsedJson, JsonFormatting.Indented);
}
catch
{
// can't parse JSON, return the original string
return str;
}
}

public static Encoding GetFileEncoding(string path)
{
Encoding encoding;
Expand Down Expand Up @@ -857,18 +880,18 @@ public static Uri CreateHttpsEndpoint(string endpointUri)
/// <summary>
/// Formats the given XML into indented way.
/// </summary>
/// <param name="xml">The input xml string</param>
/// <param name="content">The input xml string</param>
/// <returns>The formatted xml string</returns>
public static string FormatXml(string xml)
public static string TryFormatXml(string content)
{
try
{
XDocument doc = XDocument.Parse(xml);
XDocument doc = XDocument.Parse(content);
return doc.ToString();
}
catch (Exception)
{
return xml;
return content;
}
}

Expand All @@ -890,6 +913,28 @@ public static bool IsXml(string content)
}
}

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
public static string TryFormatJson(string str)
{
try
{
object parsedJson = JsonConvert.DeserializeObject(str);
return JsonConvert.SerializeObject(parsedJson, JsonFormatting.Indented);
}
catch
{
// can't parse JSON, return the original string
return str;
}
}

public static bool IsJson(string content)
{
content = content.Trim();
return content.StartsWith("{") && content.EndsWith("}")
|| content.StartsWith("[") && content.EndsWith("]");
}

public static string GetNonEmptyValue(string oldValue, string newValue)
{
return string.IsNullOrEmpty(newValue) ? oldValue : newValue;
Expand Down
Expand Up @@ -153,14 +153,14 @@ public static T GetJson<T>(this HttpClient client, string requestUri, Action<str
public static string GetXml(this HttpClient client, string requestUri, Action<string> logger)
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
return GetRawBody(client, requestUri, logger, General.FormatXml);
return GetRawBody(client, requestUri, logger, General.TryFormatXml);
}

public static T GetXml<T>(this HttpClient client, string requestUri, Action<string> logger)
where T: class, new()
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
return GetFormat<T>(client, requestUri, logger, General.FormatXml, General.DeserializeXmlString<T>);
return GetFormat<T>(client, requestUri, logger, General.TryFormatXml, General.DeserializeXmlString<T>);
}

public static T PostJson<T>(
Expand Down
@@ -0,0 +1,46 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

namespace Microsoft.WindowsAzure.Commands.Utilities.Common
{
using System.Net.Http;
using System.Text;
using System.Threading;

public class HttpRestCallLogger : MessageProcessingHandler
{
private static StringBuilder HttpLog = new StringBuilder();

public static string Flush()
{
string logs = HttpLog.ToString();
HttpLog.Clear();

return logs;
}

protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
{
HttpLog.Append(General.GetLog(response));
return response;
}

protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpLog.Append(General.GetLog(request));
return request;
}
}

}
Expand Up @@ -61,7 +61,8 @@ public WebsitesClient(SubscriptionData subscription, Action<string> logger)
WebsiteManagementClient =
CloudContext.Clients.CreateWebSiteManagementClient(new CertificateCloudCredentials(
subscriptionId, Subscription.Certificate), new Uri(Subscription.ServiceEndpoint))
.WithHandler(new StandardHeadersHandler());
.WithHandler(new StandardHeadersHandler())
.WithHandler(new HttpRestCallLogger());
}

/// <summary>
Expand Down

0 comments on commit b0e1c1a

Please sign in to comment.