Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/corelib/Configuration.cs → src/corelib/OpenStackNet.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using Flurl.Http;
using Flurl.Http.Configuration;
using Newtonsoft.Json;
Expand Down Expand Up @@ -54,6 +55,8 @@ public static void Configure(Action<FlurlHttpConfigurationOptions> configureFlur
{
// Apply our default settings
c.HttpClientFactory = new AuthenticatedHttpClientFactory();
c.AfterCall = Tracing.TraceHttpCall;
c.OnError = Tracing.TraceFailedHttpCall;

// Apply application's default settings
if (configureFlurl != null)
Expand All @@ -63,5 +66,38 @@ public static void Configure(Action<FlurlHttpConfigurationOptions> configureFlur
_isConfigured = true;
}
}

/// <summary>
/// Provides global point for programmatically configuraing tracing
/// </summary>
public static class Tracing
{
/// <summary>
/// Trace source for all HTTP requests. Default level is Error.
/// <para>
/// In your app or web.config the trace soruce name is "Flurl.Http".
/// </para>
/// </summary>
public static readonly TraceSource Http = new TraceSource("Flurl.Http", SourceLevels.Error);

/// <summary>
/// Traces a failed HTTP request
/// </summary>
/// <param name="httpCall">The Flurl HTTP call instance, containing information about the request and response.</param>
public static void TraceFailedHttpCall(HttpCall httpCall)
{
Http.TraceData(TraceEventType.Error, 0, JsonConvert.SerializeObject(httpCall, Formatting.Indented));
Http.Flush();
}

/// <summary>
/// Traces an HTTP request
/// </summary>
/// <param name="httpCall">The Flurl HTTP call instance, containing information about the request and response.</param>
public static void TraceHttpCall(HttpCall httpCall)
{
Http.TraceData(TraceEventType.Information, 0, JsonConvert.SerializeObject(httpCall, Formatting.Indented));
}
}
}
}
2 changes: 1 addition & 1 deletion src/corelib/corelib.v4.0.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
<Compile Include="Authentication\IAuthenticationProvider.cs" />
<Compile Include="Authentication\NamespaceDoc.cs" />
<Compile Include="Authentication\ServiceUrlBuilder.cs" />
<Compile Include="Configuration.cs" />
<Compile Include="OpenStackNet.cs" />
<Compile Include="ContentDeliveryNetworks\v1\Flavor.cs" />
<Compile Include="ContentDeliveryNetworks\v1\FlavorCollection.cs" />
<Compile Include="ContentDeliveryNetworks\v1\NamespaceDoc.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using net.openstack.Providers.Rackspace;
using OpenStack.Synchronous;
using Xunit;
using Xunit.Abstractions;

namespace OpenStack.ContentDeliveryNetworks.v1
{
public class ContentDeliveryNetworkServiceTests
{
private readonly ContentDeliveryNetworkService _cdnService;

public ContentDeliveryNetworkServiceTests()
public ContentDeliveryNetworkServiceTests(ITestOutputHelper testLog)
{
OpenStackNet.Tracing.Http.Listeners.Add(new XunitTraceListener(testLog));

var identity = TestIdentityProvider.GetIdentityFromEnvironment();
var authenticationProvider = new CloudIdentityProvider(identity)
{
Expand Down
52 changes: 27 additions & 25 deletions src/testing/integration/ContentDeliveryNetworks/v1/ServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Flurl.Http;
Expand All @@ -14,12 +15,13 @@ namespace OpenStack.ContentDeliveryNetworks.v1
{
public class ServiceTests
{
private readonly ITestOutputHelper _log;
private readonly ContentDeliveryNetworkService _cdnService;

public ServiceTests(ITestOutputHelper log)
public ServiceTests(ITestOutputHelper testLog)
{
_log = log;
var testOutput = new XunitTraceListener(testLog);
OpenStackNet.Tracing.Http.Listeners.Add(testOutput);
Trace.Listeners.Add(testOutput);

var identity = TestIdentityProvider.GetIdentityFromEnvironment();
var authenticationProvider = new CloudIdentityProvider(identity)
Expand All @@ -34,26 +36,26 @@ public async void CreateAServiceOnAkamai_UsingDefaults()
{
try
{
_log.WriteLine("Looking for a CDN flavor provided by Akamai...");
Trace.WriteLine("Looking for a CDN flavor provided by Akamai...");
var flavors = await _cdnService.ListFlavorsAsync();
var flavor = flavors.FirstOrDefault(x => x.Providers.Any(p => string.Equals(p.Name, "Akamai", StringComparison.OrdinalIgnoreCase)));
Assert.NotNull(flavor);
var akamaiFlavor = flavor.Id;
_log.WriteLine("Found the {0} flavor", akamaiFlavor);
Trace.WriteLine(string.Format("Found the {0} flavor", akamaiFlavor));

_log.WriteLine("Creating a CDN service using defaults for anything I can omit...");
Trace.WriteLine("Creating a CDN service using defaults for anything I can omit...");
var domains = new[] {new ServiceDomain("mirror.example.com")};
var origins = new[] {new ServiceOrigin("example.com")};
var serviceDefinition = new ServiceDefinition("ci-test", akamaiFlavor, domains, origins);
var serviceId = await _cdnService.CreateServiceAsync(serviceDefinition);
_log.WriteLine("Service was created: {0}", serviceId);
Trace.WriteLine(string.Format("Service was created: {0}", serviceId));

try
{
_log.WriteLine("Waiting for the service to be deployed...");
var service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => _log.WriteLine("...")));
Trace.WriteLine("Waiting for the service to be deployed...");
var service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => Trace.WriteLine("...")));

_log.WriteLine("Verifying service matches the requested definition...");
Trace.WriteLine("Verifying service matches the requested definition...");
Assert.Equal("ci-test", service.Name);
Assert.Equal(serviceDefinition.FlavorId, service.FlavorId);

Expand All @@ -63,31 +65,31 @@ public async void CreateAServiceOnAkamai_UsingDefaults()
Assert.Equal(serviceDefinition.Domains.Count, service.Domains.Count());
Assert.Equal(serviceDefinition.Domains.First().Domain, service.Domains.First().Domain);

_log.WriteLine("Updating the service...");
Trace.WriteLine("Updating the service...");
var patch = new JsonPatchDocument<ServiceDefinition>();
patch.Replace(x => x.Name, "ci-test2");
var intranetOnly = new ServiceRestriction("intranet", new[] {new ServiceRestrictionRule("intranet", "intranet.example.com")});
patch.Add(x => x.Restrictions, intranetOnly, 0);
await _cdnService.UpdateServiceAsync(serviceId, patch);

_log.WriteLine("Waiting for the service changes to be deployed...");
service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => _log.WriteLine("...")));
Trace.WriteLine("Waiting for the service changes to be deployed...");
service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => Trace.WriteLine("...")));

_log.WriteLine("Verifying service matches updated definition...");
Trace.WriteLine("Verifying service matches updated definition...");
Assert.Equal("ci-test2", service.Name);
Assert.Equal(JsonConvert.SerializeObject(intranetOnly), JsonConvert.SerializeObject(service.Restrictions.First()));

_log.WriteLine("Purging all assets on service");
Trace.WriteLine("Purging all assets on service");
await _cdnService.PurgeCachedAssetsAsync(serviceId);
}
finally
{
_log.WriteLine("Cleaning up any test data...");
Trace.WriteLine("Cleaning up any test data...");

_log.WriteLine("Removing the service...");
Trace.WriteLine("Removing the service...");
_cdnService.DeleteService(serviceId);
_cdnService.WaitForServiceDeleted(serviceId);
_log.WriteLine("The service was cleaned up sucessfully.");
Trace.WriteLine("The service was cleaned up sucessfully.");
}
}
catch (FlurlHttpException ex)
Expand All @@ -113,7 +115,7 @@ public async void FindServiceOnAPage()
{
if (currentPage.Any(x => x.Name == "ci-test3"))
{
_log.WriteLine("Found the desired service");
Trace.WriteLine("Found the desired service");
break;
}

Expand All @@ -126,17 +128,17 @@ public async void FindServiceOnAPage()
}
finally
{
_log.WriteLine("Cleaning up any test data...");
Trace.WriteLine("Cleaning up any test data...");

_log.WriteLine("Removing the services...");
Trace.WriteLine("Removing the services...");
var deletes = serviceIds.Select(serviceId => _cdnService
.DeleteServiceAsync(serviceId)
.ContinueWith(t => _cdnService.WaitForServiceDeletedAsync(serviceId))
.ContinueWith(t => _log.WriteLine("Service was deleted: {0}", serviceId)))
.ContinueWith(t => Trace.WriteLine(string.Format("Service was deleted: {0}", serviceId))))
.ToArray();

Task.WaitAll(deletes);
_log.WriteLine("The services were cleaned up sucessfully.");
Trace.WriteLine("The services were cleaned up sucessfully.");

}
}
Expand All @@ -146,12 +148,12 @@ private async Task<string> CreateService(string name, string domain, string orig
var flavors = await _cdnService.ListFlavorsAsync();
var flavor = flavors.First();

_log.WriteLine("Creating CDN Service: {0} for {1} originating from {2}", name, domain, origin);
Trace.WriteLine(string.Format("Creating CDN Service: {0} for {1} originating from {2}", name, domain, origin));
var domains = new[] { new ServiceDomain(domain) };
var origins = new[] { new ServiceOrigin(origin) };
var serviceDefinition = new ServiceDefinition(name, flavor.Id, domains, origins);
var serviceId = await _cdnService.CreateServiceAsync(serviceDefinition);
_log.WriteLine("Service was created: {0}", serviceId);
Trace.WriteLine("Service was created: {0}", serviceId);
return serviceId;
}
}
Expand Down
28 changes: 28 additions & 0 deletions src/testing/integration/XunitTraceListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Diagnostics;
using Xunit.Abstractions;

namespace OpenStack
{
public class XunitTraceListener : TraceListener
{
private readonly ITestOutputHelper _testLog;

public XunitTraceListener(ITestOutputHelper testLog)
{
_testLog = testLog;
}

public override void Write(string message)
{
if (message.StartsWith(OpenStackNet.Tracing.Http.Name))
return;

_testLog.WriteLine(message);
}

public override void WriteLine(string message)
{
_testLog.WriteLine(message);
}
}
}
3 changes: 2 additions & 1 deletion src/testing/integration/integration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
<Compile Include="Providers\Rackspace\UserObjectStorageTests.cs" />
<Compile Include="Providers\Rackspace\UserQueuesTests.cs" />
<Compile Include="Providers\Rackspace\UserServerTests.cs" />
<Compile Include="XunitTraceListener.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\corelib\corelib.v4.0.csproj">
Expand Down Expand Up @@ -185,4 +186,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
5 changes: 5 additions & 0 deletions src/testing/unit/HttpTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public HttpTest()
FlurlHttp.Configure(opts =>
{
opts.HttpClientFactory = new TestHttpClientFactory(this);
opts.AfterCall = call => // Restore handler which was nuked by the base HttpTest
{
CallLog.Add(call);
OpenStackNet.Tracing.TraceHttpCall(call);
};
});
}

Expand Down