1
0
Форкнуть 0

Merge pull request #2 from Microsoft/sergkanz/functionalTests

Functional tests infrastracture
This commit is contained in:
Sergey Kanzhelev 2015-03-27 11:08:27 -07:00
Родитель 2503d0e245 d2998c2efb
Коммит e271f2763e
20 изменённых файлов: 634 добавлений и 353 удалений

Просмотреть файл

@ -18,6 +18,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApplicationInsights.AspNet.
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleWebAppIntegration", "test\SampleWebAppIntegration\SampleWebAppIntegration.kproj", "{330152EC-1092-41F0-9F96-C3438E07FCC2}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FunctionalTestUtils", "test\FunctionalTestUtils\FunctionalTestUtils.kproj", "{B7217A00-66FA-49A8-8EF3-39C07E1F7E33}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -36,6 +38,10 @@ Global
{330152EC-1092-41F0-9F96-C3438E07FCC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{330152EC-1092-41F0-9F96-C3438E07FCC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{330152EC-1092-41F0-9F96-C3438E07FCC2}.Release|Any CPU.Build.0 = Release|Any CPU
{B7217A00-66FA-49A8-8EF3-39C07E1F7E33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7217A00-66FA-49A8-8EF3-39C07E1F7E33}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7217A00-66FA-49A8-8EF3-39C07E1F7E33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7217A00-66FA-49A8-8EF3-39C07E1F7E33}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -44,5 +50,6 @@ Global
{95EC3635-22E4-4C3A-A066-F5823A0648DA} = {2E6DDE9E-8C75-4F9C-8906-08EBDD6E73EF}
{2766D8AF-C20B-4F3A-8260-6C2D39B7A8A0} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{330152EC-1092-41F0-9F96-C3438E07FCC2} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{B7217A00-66FA-49A8-8EF3-39C07E1F7E33} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,36 +1,36 @@
namespace Microsoft.ApplicationInsights.AspNet
{
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System;
using System.Threading.Tasks;
public sealed class ApplicationInsightsExceptionMiddleware
{
private readonly RequestDelegate next;
private readonly TelemetryClient telemetryClient;
public sealed class ApplicationInsightsExceptionMiddleware
{
private readonly RequestDelegate next;
private readonly TelemetryClient telemetryClient;
public ApplicationInsightsExceptionMiddleware(RequestDelegate next, TelemetryClient client)
{
this.next = next;
this.telemetryClient = client;
}
public ApplicationInsightsExceptionMiddleware(RequestDelegate next, TelemetryClient client)
{
this.next = next;
this.telemetryClient = client;
}
public async Task Invoke(HttpContext httpContext)
{
try
{
await this.next.Invoke(httpContext);
}
catch (Exception exp)
{
if (this.telemetryClient != null)
{
this.telemetryClient.TrackException(exp);
}
public async Task Invoke(HttpContext httpContext)
{
try
{
await this.next.Invoke(httpContext);
}
catch (Exception exp)
{
if (this.telemetryClient != null)
{
this.telemetryClient.TrackException(exp);
}
throw;
}
}
}
throw;
}
}
}
}

Просмотреть файл

@ -1,70 +1,71 @@
namespace Microsoft.ApplicationInsights.AspNet
{
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.ApplicationInsights.AspNet.DataCollection;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using System;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.ApplicationInsights.AspNet.DataCollection;
using Microsoft.ApplicationInsights.AspNet.Implementation;
public static class ApplicationInsightsExtensions
{
public static IApplicationBuilder UseApplicationInsightsRequestTelemetry(this IApplicationBuilder app)
{
app.UseMiddleware<ApplicationInsightsRequestMiddleware>();
return app;
}
public static class ApplicationInsightsExtensions
{
public static IApplicationBuilder UseApplicationInsightsRequestTelemetry(this IApplicationBuilder app)
{
app.UseMiddleware<ApplicationInsightsRequestMiddleware>();
return app;
}
public static IApplicationBuilder UseApplicationInsightsExceptionTelemetry(this IApplicationBuilder app)
{
app.UseMiddleware<ApplicationInsightsExceptionMiddleware>();
return app;
}
public static IApplicationBuilder UseApplicationInsightsExceptionTelemetry(this IApplicationBuilder app)
{
app.UseMiddleware<ApplicationInsightsExceptionMiddleware>();
return app;
}
public static IApplicationBuilder SetApplicationInsightsTelemetryDeveloperMode(this IApplicationBuilder app)
{
TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;
return app;
}
public static IApplicationBuilder SetApplicationInsightsTelemetryDeveloperMode(this IApplicationBuilder app)
{
TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;
return app;
}
public static void AddApplicationInsightsTelemetry(this IServiceCollection services, IConfiguration config)
{
TelemetryConfiguration.Active.InstrumentationKey = config.Get("ApplicationInsights:InstrumentationKey");
public static void AddApplicationInsightsTelemetry(this IServiceCollection services, IConfiguration config)
{
TelemetryConfiguration.Active.InstrumentationKey = config.Get("ApplicationInsights:InstrumentationKey");
services.AddSingleton<TelemetryClient>((svcs) => {
TelemetryConfiguration.Active.TelemetryInitializers.Add(new WebClientIpHeaderTelemetryInitializer(svcs));
TelemetryConfiguration.Active.TelemetryInitializers.Add(new WebUserAgentTelemetryInitializer(svcs));
return new TelemetryClient();
services.AddSingleton<TelemetryClient>((svcs) => {
TelemetryConfiguration.Active.TelemetryInitializers.Add(new WebClientIpHeaderTelemetryInitializer(svcs));
return new TelemetryClient();
});
services.AddScoped<RequestTelemetry>((svcs) => {
var rt = new RequestTelemetry();
// this is workaround to inject proper instrumentation key into javascript:
rt.Context.InstrumentationKey = svcs.GetService<TelemetryClient>().Context.InstrumentationKey;
return rt;
});
services.AddScoped<RequestTelemetry>((svcs) => {
var rt = new RequestTelemetry();
// this is workaround to inject proper instrumentation key into javascript:
rt.Context.InstrumentationKey = svcs.GetService<TelemetryClient>().Context.InstrumentationKey;
return rt;
});
services.AddScoped<HttpContextHolder>();
}
services.AddScoped<HttpContextHolder>();
}
public static HtmlString ApplicationInsightsJavaScriptSnippet(this IHtmlHelper helper, string instrumentationKey)
{
//see: https://github.com/aspnet/Mvc/issues/2056
//var client = (TelemetryClient)helper.ViewContext.HttpContext.ApplicationServices.GetService(typeof(TelemetryClient));
return new HtmlString(@"<script language='javascript'>
var appInsights = window.appInsights || function(config){
function s(config){t[config]=function(){var i=arguments; t.queue.push(function(){ t[config].apply(t, i)})}
}
var t = { config:config }, r = document, f = window, e = ""script"", o = r.createElement(e), i, u;for(o.src=config.url||""//az416426.vo.msecnd.net/scripts/a/ai.0.js"",r.getElementsByTagName(e)[0].parentNode.appendChild(o),t.cookie=r.cookie,t.queue=[],i=[""Event"",""Exception"",""Metric"",""PageView"",""Trace""];i.length;)s(""track""+i.pop());return config.disableExceptionTracking||(i=""onerror"",s(""_""+i),u=f[i],f[i]=function(config, r, f, e, o) { var s = u && u(config, r, f, e, o); return s !== !0 && t[""_"" + i](config, r, f, e, o),s}),t
public static HtmlString ApplicationInsightsJavaScriptSnippet(this IHtmlHelper helper, string instrumentationKey)
{
//see: https://github.com/aspnet/Mvc/issues/2056
//var client = (TelemetryClient)helper.ViewContext.HttpContext.ApplicationServices.GetService(typeof(TelemetryClient));
return new HtmlString(@"<script language='javascript'>
var appInsights = window.appInsights || function(config){
function s(config){t[config]=function(){var i=arguments; t.queue.push(function(){ t[config].apply(t, i)})}
}
var t = { config:config }, r = document, f = window, e = ""script"", o = r.createElement(e), i, u;for(o.src=config.url||""//az416426.vo.msecnd.net/scripts/a/ai.0.js"",r.getElementsByTagName(e)[0].parentNode.appendChild(o),t.cookie=r.cookie,t.queue=[],i=[""Event"",""Exception"",""Metric"",""PageView"",""Trace""];i.length;)s(""track""+i.pop());return config.disableExceptionTracking||(i=""onerror"",s(""_""+i),u=f[i],f[i]=function(config, r, f, e, o) { var s = u && u(config, r, f, e, o); return s !== !0 && t[""_"" + i](config, r, f, e, o),s}),t
}({
instrumentationKey:""" + instrumentationKey + @"""
});
instrumentationKey:""" + instrumentationKey + @"""
});
window.appInsights=appInsights;
appInsights.trackPageView();
window.appInsights=appInsights;
appInsights.trackPageView();
</script>");
}
}
}
}
}

Просмотреть файл

@ -1,63 +1,63 @@
namespace Microsoft.ApplicationInsights.AspNet
{
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.RequestContainer;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.RequestContainer;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
public sealed class ApplicationInsightsRequestMiddleware
{
private readonly RequestDelegate next;
private readonly TelemetryClient telemetryClient;
private readonly IServiceProvider serviceProvider;
public sealed class ApplicationInsightsRequestMiddleware
{
private readonly RequestDelegate next;
private readonly TelemetryClient telemetryClient;
private readonly IServiceProvider serviceProvider;
public ApplicationInsightsRequestMiddleware(IServiceProvider svcs, RequestDelegate next, TelemetryClient client)
{
this.serviceProvider = svcs;
public ApplicationInsightsRequestMiddleware(IServiceProvider svcs, RequestDelegate next, TelemetryClient client)
{
this.serviceProvider = svcs;
this.telemetryClient = client;
this.next = next;
}
this.next = next;
}
public async Task Invoke(HttpContext httpContext)
{
this.serviceProvider.GetService<HttpContextHolder>().Context = httpContext;
public async Task Invoke(HttpContext httpContext)
{
this.serviceProvider.GetService<HttpContextHolder>().Context = httpContext;
var sw = new Stopwatch();
sw.Start();
var sw = new Stopwatch();
sw.Start();
var now = DateTimeOffset.UtcNow;
var now = DateTimeOffset.UtcNow;
try
{
await this.next.Invoke(httpContext);
}
finally
{
if (this.telemetryClient != null)
{
sw.Stop();
try
{
await this.next.Invoke(httpContext);
}
finally
{
if (this.telemetryClient != null)
{
sw.Stop();
var telemetry = this.serviceProvider.GetService<RequestTelemetry>();
telemetry.Name = httpContext.Request.Method + " " + httpContext.Request.Path.Value;
telemetry.Timestamp = now;
telemetry.Duration = sw.Elapsed;
telemetry.ResponseCode = httpContext.Response.StatusCode.ToString();
telemetry.Success = httpContext.Response.StatusCode < 400;
var telemetry = this.serviceProvider.GetService<RequestTelemetry>();
telemetry.Name = httpContext.Request.Method + " " + httpContext.Request.Path.Value;
telemetry.Timestamp = now;
telemetry.Duration = sw.Elapsed;
telemetry.ResponseCode = httpContext.Response.StatusCode.ToString();
telemetry.Success = httpContext.Response.StatusCode < 400;
this.telemetryClient.TrackRequest(telemetry);
}
}
}
}
this.telemetryClient.TrackRequest(telemetry);
}
}
}
}
}

Просмотреть файл

@ -1,156 +1,156 @@

namespace Microsoft.ApplicationInsights.AspNet.DataCollection
{
using Microsoft.ApplicationInsights.Extensibility;
using System;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Interfaces;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using Microsoft.ApplicationInsights.Extensibility;
using System;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Interfaces;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
/// <summary>
/// This telemetry initializer extracts client IP address and populates telemetry.Context.Location.Ip property.
/// Lot's of code reuse from Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebClientIpHeaderTelemetryInitializer
/// </summary>
public class WebClientIpHeaderTelemetryInitializer : ITelemetryInitializer
{
private IServiceProvider serviceProvider;
/// <summary>
/// This telemetry initializer extracts client IP address and populates telemetry.Context.Location.Ip property.
/// Lot's of code reuse from Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebClientIpHeaderTelemetryInitializer
/// </summary>
public class WebClientIpHeaderTelemetryInitializer : ITelemetryInitializer
{
private IServiceProvider serviceProvider;
private readonly char[] HeaderValuesSeparatorDefault = new char[] { ',' };
private const string HeaderNameDefault = "X-Forwarded-For";
private readonly char[] HeaderValuesSeparatorDefault = new char[] { ',' };
private const string HeaderNameDefault = "X-Forwarded-For";
private char[] headerValueSeparators;
private char[] headerValueSeparators;
private readonly ICollection<string> headerNames;
private readonly ICollection<string> headerNames;
public WebClientIpHeaderTelemetryInitializer(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
this.headerNames = new List<string>();
this.HeaderNames.Add(HeaderNameDefault);
this.UseFirstIp = true;
this.headerValueSeparators = HeaderValuesSeparatorDefault;
}
public WebClientIpHeaderTelemetryInitializer(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
this.headerNames = new List<string>();
this.HeaderNames.Add(HeaderNameDefault);
this.UseFirstIp = true;
this.headerValueSeparators = HeaderValuesSeparatorDefault;
}
/// <summary>
/// Gets or sets comma separated list of request header names that is used to check client id.
/// </summary>
public ICollection<string> HeaderNames
{
get
{
return this.headerNames;
}
}
/// <summary>
/// Gets or sets comma separated list of request header names that is used to check client id.
/// </summary>
public ICollection<string> HeaderNames
{
get
{
return this.headerNames;
}
}
/// <summary>
/// Gets or sets a header values separator.
/// </summary>
public string HeaderValueSeparators
{
get
{
return string.Concat(this.headerValueSeparators);
}
/// <summary>
/// Gets or sets a header values separator.
/// </summary>
public string HeaderValueSeparators
{
get
{
return string.Concat(this.headerValueSeparators);
}
set
{
if (!string.IsNullOrEmpty(value))
{
this.headerValueSeparators = value.ToCharArray();
}
}
}
set
{
if (!string.IsNullOrEmpty(value))
{
this.headerValueSeparators = value.ToCharArray();
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the first or the last IP should be used from the lists of IPs in the header.
/// </summary>
public bool UseFirstIp { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the first or the last IP should be used from the lists of IPs in the header.
/// </summary>
public bool UseFirstIp { get; set; }
public void Initialize(ITelemetry telemetry)
{
var request = this.serviceProvider.GetService<RequestTelemetry>();
if (!string.IsNullOrEmpty(request.Context.Location.Ip))
{
telemetry.Context.Location.Ip = request.Context.Location.Ip;
}
else
{
var context = this.serviceProvider.GetService<HttpContextHolder>().Context;
public void Initialize(ITelemetry telemetry)
{
var request = this.serviceProvider.GetService<RequestTelemetry>();
if (!string.IsNullOrEmpty(request.Context.Location.Ip))
{
telemetry.Context.Location.Ip = request.Context.Location.Ip;
}
else
{
var context = this.serviceProvider.GetService<HttpContextHolder>().Context;
string resultIp = null;
foreach (var name in this.HeaderNames)
{
var headerValue = context.Request.Headers[name];
if (!string.IsNullOrEmpty(headerValue))
{
var ip = GetIpFromHeader(headerValue);
ip = CutPort(ip);
if (IsCorrectIpAddress(ip))
{
resultIp = ip;
break;
}
}
}
string resultIp = null;
foreach (var name in this.HeaderNames)
{
var headerValue = context.Request.Headers[name];
if (!string.IsNullOrEmpty(headerValue))
{
var ip = GetIpFromHeader(headerValue);
ip = CutPort(ip);
if (IsCorrectIpAddress(ip))
{
resultIp = ip;
break;
}
}
}
if (string.IsNullOrEmpty(resultIp))
{
var connectionFeature = context.GetFeature<IHttpConnectionFeature>();
if (string.IsNullOrEmpty(resultIp))
{
var connectionFeature = context.GetFeature<IHttpConnectionFeature>();
if (connectionFeature != null)
{
resultIp = connectionFeature.RemoteIpAddress.ToString();
}
}
if (connectionFeature != null)
{
resultIp = connectionFeature.RemoteIpAddress.ToString();
}
}
request.Context.Location.Ip = resultIp;
telemetry.Context.Location.Ip = resultIp;
}
}
request.Context.Location.Ip = resultIp;
telemetry.Context.Location.Ip = resultIp;
}
}
private static string CutPort(string address)
{
// For Web sites in Azure header contains ip address with port e.g. 50.47.87.223:54464
int portSeparatorIndex = address.IndexOf(":", StringComparison.OrdinalIgnoreCase);
private static string CutPort(string address)
{
// For Web sites in Azure header contains ip address with port e.g. 50.47.87.223:54464
int portSeparatorIndex = address.IndexOf(":", StringComparison.OrdinalIgnoreCase);
if (portSeparatorIndex > 0)
{
return address.Substring(0, portSeparatorIndex);
}
if (portSeparatorIndex > 0)
{
return address.Substring(0, portSeparatorIndex);
}
return address;
}
return address;
}
private static bool IsCorrectIpAddress(string address)
{
IPAddress outParameter;
address = address.Trim();
private static bool IsCorrectIpAddress(string address)
{
IPAddress outParameter;
address = address.Trim();
// Core SDK does not support setting Location.Ip to malformed ip address
if (IPAddress.TryParse(address, out outParameter))
{
// Also SDK supports only ipv4!
if (outParameter.AddressFamily == AddressFamily.InterNetwork)
{
return true;
}
}
// Core SDK does not support setting Location.Ip to malformed ip address
if (IPAddress.TryParse(address, out outParameter))
{
// Also SDK supports only ipv4!
if (outParameter.AddressFamily == AddressFamily.InterNetwork)
{
return true;
}
}
return false;
}
return false;
}
private string GetIpFromHeader(string clientIpsFromHeader)
{
var ips = clientIpsFromHeader.Split(this.headerValueSeparators, StringSplitOptions.RemoveEmptyEntries);
return this.UseFirstIp ? ips[0].Trim() : ips[ips.Length - 1].Trim();
}
private string GetIpFromHeader(string clientIpsFromHeader)
{
var ips = clientIpsFromHeader.Split(this.headerValueSeparators, StringSplitOptions.RemoveEmptyEntries);
return this.UseFirstIp ? ips[0].Trim() : ips[ips.Length - 1].Trim();
}
}
}
}

Просмотреть файл

@ -1,35 +1,35 @@
namespace Microsoft.ApplicationInsights.AspNet.DataCollection
{
using System;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Framework.DependencyInjection;
using System;
using Microsoft.ApplicationInsights.AspNet.Implementation;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Framework.DependencyInjection;
/// <summary>
/// Telemetry initializer populates user agent (telemetry.Context.User.UserAgent) for
/// all telemetry data items.
/// </summary>
public class WebUserAgentTelemetryInitializer : ITelemetryInitializer
{
private IServiceProvider serviceProvider;
/// <summary>
/// Telemetry initializer populates user agent (telemetry.Context.User.UserAgent) for
/// all telemetry data items.
/// </summary>
public class WebUserAgentTelemetryInitializer : ITelemetryInitializer
{
private IServiceProvider serviceProvider;
public WebUserAgentTelemetryInitializer(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public WebUserAgentTelemetryInitializer(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public void Initialize(ITelemetry telemetry)
{
var request = this.serviceProvider.GetService<RequestTelemetry>();
if (string.IsNullOrEmpty(request.Context.User.UserAgent))
{
var context = this.serviceProvider.GetService<HttpContextHolder>().Context;
var userAgent = context.Request.Headers["User-Agent"];
request.Context.User.UserAgent = userAgent;
}
telemetry.Context.User.UserAgent = request.Context.User.UserAgent;
}
}
public void Initialize(ITelemetry telemetry)
{
var request = this.serviceProvider.GetService<RequestTelemetry>();
if (string.IsNullOrEmpty(request.Context.User.UserAgent))
{
var context = this.serviceProvider.GetService<HttpContextHolder>().Context;
var userAgent = context.Request.Headers["User-Agent"];
request.Context.User.UserAgent = userAgent;
}
telemetry.Context.User.UserAgent = request.Context.User.UserAgent;
}
}
}

Просмотреть файл

@ -5,6 +5,6 @@ namespace Microsoft.ApplicationInsights.AspNet.Implementation
{
public class HttpContextHolder
{
public HttpContext Context;
public HttpContext Context;
}
}

Просмотреть файл

@ -1,24 +1,24 @@
{
"version": "0.30.0.1-beta",
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta3",
"Microsoft.Framework.Logging": "1.0.0-beta3",
"Microsoft.AspNet.Http.Extensions": "1.0.0-beta3",
"Microsoft.AspNet.RequestContainer": "1.0.0-beta3",
"Microsoft.AspNet.Mvc.Core": "6.0.0-beta3"
},
"version": "0.30.0.1-beta",
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta3",
"Microsoft.Framework.Logging": "1.0.0-beta3",
"Microsoft.AspNet.Http.Extensions": "1.0.0-beta3",
"Microsoft.AspNet.RequestContainer": "1.0.0-beta3",
"Microsoft.AspNet.Mvc.Core": "6.0.0-beta3"
},
"frameworks": {
"aspnet50": {
"dependencies": {
"Microsoft.ApplicationInsights": "0.13.4-build00460"
}
},
"aspnetcore50": {
"dependencies": {
"System.Runtime": "4.0.20-*",
"Microsoft.ApplicationInsights.Portable": "0.30.0.0-beta"
}
}
}
"frameworks": {
"aspnet50": {
"dependencies": {
"Microsoft.ApplicationInsights": "0.13.4-build00460"
}
},
"aspnetcore50": {
"dependencies": {
"System.Runtime": "4.0.20-*",
"Microsoft.ApplicationInsights.Portable": "0.30.0.0-beta"
}
}
}
}

Просмотреть файл

@ -1,15 +1,15 @@

namespace Microsoft.ApplicationInsights.AspNet.Tests
{
using System;
using Xunit;
using System;
using Xunit;
public class Sample
public class Sample
{
[Fact]
public void TrueIsTrue()
{
Assert.True(true);
Assert.True(true);
}
}
}

Просмотреть файл

@ -1,15 +1,15 @@
namespace Microsoft.ApplicationInsights.AspNet.Tests
{
using System;
using Xunit;
using System;
using Xunit;
public class WebUserAgentTelemetryInitializerTests
public class WebUserAgentTelemetryInitializerTests
{
[Fact]
public void WebUserAgentTelemetryInitializerReadsProperHeader()
{
//TODO: need to implement after Anastasia will create an example on how it should be implemented
Assert.True(true);
}
}
[Fact]
public void WebUserAgentTelemetryInitializerReadsProperHeader()
{
//TODO: need to implement after Anastasia will create an example on how it should be implemented
Assert.True(true);
}
}
}

Просмотреть файл

@ -11,5 +11,5 @@
"frameworks": {
"aspnet50": { },
"aspnetcore50": { }
},
}
}

Просмотреть файл

@ -0,0 +1,27 @@

namespace FunctionalTestUtils
{
using Microsoft.ApplicationInsights.Channel;
using System.Collections.Generic;
internal class BackTelemetryChannel : ITelemetryChannel
{
IList<ITelemetry> buffer;
public BackTelemetryChannel(IList<ITelemetry> buffer)
{
this.buffer = buffer;
}
public bool DeveloperMode { get; set; }
public void Dispose()
{
}
public void Send(ITelemetry item)
{
this.buffer.Add(item);
}
}
}

Просмотреть файл

@ -0,0 +1,40 @@
namespace FunctionalTestUtils
{
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Framework.DependencyInjection;
using System;
using System.Collections.Generic;
public static class BackTelemetryChannelExtensions
{
/// <summary>
/// I know, statics are bad. Let's refactor when it will become a problem
/// </summary>
private static BackTelemetryChannel channel;
/// <summary>
/// If applciaiton is running under functional tests - in process channel will be used.
/// Otherwise - regular channel will be used
/// </summary>
/// <param name="services"></param>
public static void AddFunctionalTestTelemetryChannel(this IServiceCollection services)
{
if (channel != null)
{
TelemetryConfiguration.Active.TelemetryChannel = channel;
}
}
/// <summary>
/// I haven't implemented Reset method to delete channel. Since an applicaiton will either be used by
/// unit tests or started directly - it should not be a big problem, every unit test will override
/// channel with it's own version.
/// </summary>
/// <param name="buffer"></param>
public static void InitializeFunctionalTestTelemetryChannel(IList<ITelemetry> buffer)
{
channel = new BackTelemetryChannel(buffer);
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>b7217a00-66fa-49a8-8ef3-39c07e1f7e33</ProjectGuid>
<RootNamespace>FunctionalTestUtils</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Просмотреть файл

@ -0,0 +1,55 @@
namespace FunctionalTestUtils
{
using Microsoft.AspNet.Hosting;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using System;
public class InProcessServer
{
private string url = "http://localhost:" + (new Random(239).Next(5000, 8000)).ToString();
private string assemblyName = "ConsoleTest";
public InProcessServer(string currentAssemblyName)
{
this.assemblyName = currentAssemblyName;
}
public string BaseHost
{
get
{
return this.url;
}
}
public IDisposable Start()
{
var customConfig = new NameValueConfigurationSource();
customConfig.Set("server.urls", this.BaseHost);
var config = new Configuration();
config.Add(customConfig);
var serviceCollection = HostingServices.Create(null);
var services = serviceCollection.BuildServiceProvider();
var context = new HostingContext()
{
Services = services,
Configuration = config,
ServerName = "Microsoft.AspNet.Server.WebListener",
ApplicationName = this.assemblyName,
EnvironmentName = "Production"
};
var hostingEngine = services.GetService<IHostingEngine>();
if (hostingEngine == null)
{
throw new Exception("TODO: IHostingEngine service not available exception");
}
return hostingEngine.Start(context);
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
namespace FunctionalTestUtils
{
using Microsoft.Framework.ConfigurationModel;
using System;
using System.Collections.Generic;
public class NameValueConfigurationSource : IConfigurationSource
{
private Dictionary<string, string> _config = new Dictionary<string, string>();
public NameValueConfigurationSource()
{
}
public void Load()
{
//should already be loaded
}
public IEnumerable<string> ProduceSubKeys(IEnumerable<string> earlierKeys, string prefix, string delimiter)
{
throw new NotImplementedException();
}
public void Set(string key, string value)
{
_config.Add(key, value);
}
public bool TryGet(string key, out string value)
{
return _config.TryGetValue(key, out value);
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
{
"version": "1.0.0-*",
"dependencies": {
"Microsoft.AspNet.Diagnostics": "1.0.0-beta3",
"Microsoft.AspNet.Hosting": "1.0.0-beta3",
"Microsoft.AspNet.Mvc": "6.0.0-beta3",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta3",
"xunit": "2.1.0.0-beta1-build2945",
"xunit.runner.aspnet": "2.1.0.0-beta1-build60",
"xunit.runner.visualstudio": "2.1.0.0-beta1-build1051",
"Microsoft.Net.Http.Client": "1.0.0-*"
},
"frameworks": {
"aspnet50": {
"dependencies": {
"Microsoft.ApplicationInsights": "0.13.4-build00460"
}
},
"aspnetcore50": {
"dependencies": {
"System.Runtime": "4.0.20-beta-22523",
"Microsoft.ApplicationInsights.Portable": "0.30.0.0-beta"
}
}
}
}

Просмотреть файл

@ -0,0 +1,61 @@
namespace SampleWebAppIntegration.FunctionalTest
{
using Xunit;
using System.Net.Http;
using System.Net;
using FunctionalTestUtils;
using System.Collections.Generic;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
public class SuccessScenario
{
[Fact]
public async void ServerReturns200WithMonitoring()
{
InProcessServer server = new InProcessServer("SampleWebAppIntegration");
List<ITelemetry> buffer = new List<ITelemetry>();
BackTelemetryChannelExtensions.InitializeFunctionalTestTelemetryChannel(buffer);
using (server.Start())
{
HttpClient client = new HttpClient();
var result = await client.GetAsync(server.BaseHost);
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
Assert.Equal(1, buffer.Count);
ITelemetry telemetry = buffer[0];
Assert.IsAssignableFrom(typeof(RequestTelemetry), telemetry);
RequestTelemetry request = (RequestTelemetry)telemetry;
Assert.Equal("200", request.ResponseCode);
Assert.Equal("GET /", request.Name);
}
}
[Fact]
public async void ServerReturns404ForNotExistingController()
{
InProcessServer server = new InProcessServer("SampleWebAppIntegration");
List<ITelemetry> buffer = new List<ITelemetry>();
BackTelemetryChannelExtensions.InitializeFunctionalTestTelemetryChannel(buffer);
using (server.Start())
{
HttpClient client = new HttpClient();
var result = await client.GetAsync(server.BaseHost + "/not/existing/controller");
Assert.Equal(HttpStatusCode.NotFound, result.StatusCode);
Assert.Equal(1, buffer.Count);
ITelemetry telemetry = buffer[0];
Assert.IsAssignableFrom(typeof(RequestTelemetry), telemetry);
RequestTelemetry request = (RequestTelemetry)telemetry;
Assert.Equal("404", request.ResponseCode);
}
}
}
}

Просмотреть файл

@ -14,6 +14,7 @@ using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
using Microsoft.Framework.Logging.Console;
using SampleWebAppIntegration.Models;
using FunctionalTestUtils;
namespace SampleWebAppIntegration
{
@ -32,11 +33,13 @@ namespace SampleWebAppIntegration
// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
// Add Application Insights services to the services container.
services.AddApplicationInsightsTelemetry(Configuration);
// Add Application Insights services to the services container.
services.AddApplicationInsightsTelemetry(Configuration);
// Add EF services to the services container.
services.AddEntityFramework(Configuration)
services.AddFunctionalTestTelemetryChannel();
// Add EF services to the services container.
services.AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>();
@ -47,42 +50,42 @@ namespace SampleWebAppIntegration
// Add MVC services to the services container.
services.AddMvc();
// Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
// You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
// services.AddWebApiConventions();
}
// Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
// You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
// services.AddWebApiConventions();
}
// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
// Configure the HTTP request pipeline.
// Add the console logger.
loggerfactory.AddConsole();
// Add Application Insights monitoring to the request pipeline as a very first middleware.
app.UseApplicationInsightsRequestTelemetry();
// Add Application Insights monitoring to the request pipeline as a very first middleware.
app.UseApplicationInsightsRequestTelemetry();
// Add the following to the request pipeline only in development environment.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
// Add the following to the request pipeline only in development environment.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
app.UseBrowserLink();
app.UseErrorPage(ErrorPageOptions.ShowAll);
app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
// Set immediate delivery for Application Insights events.
app.SetApplicationInsightsTelemetryDeveloperMode();
}
else
// Set immediate delivery for Application Insights events.
app.SetApplicationInsightsTelemetryDeveloperMode();
}
else
{
// Add Error handling middleware which catches all application specific errors and
// send the request to the following path or controller action.
app.UseErrorHandler("/Home/Error");
}
// Add Application Insights exceptions handling to the request pipeline.
app.UseApplicationInsightsExceptionTelemetry();
// Add Application Insights exceptions handling to the request pipeline.
app.UseApplicationInsightsExceptionTelemetry();
// Add static files to the request pipeline.
app.UseStaticFiles();
// Add static files to the request pipeline.
app.UseStaticFiles();
// Add cookie-based authentication to the request pipeline.
app.UseIdentity();

Просмотреть файл

@ -19,13 +19,18 @@
"Microsoft.Framework.Logging": "1.0.0-beta3",
"Microsoft.Framework.Logging.Console": "1.0.0-beta3",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta3",
"ApplicationInsights.AspNet": "0.30.0.1-beta"
"ApplicationInsights.AspNet": "0.30.0.1-beta",
"FunctionalTestUtils": "1.0.0-*",
"xunit": "2.1.0.0-beta1-build2945",
"xunit.runner.aspnet": "2.1.0.0-beta1-build60",
"xunit.runner.visualstudio": "2.1.0.0-beta1-build1051",
},
"commands": {
/* Change the port number when you are self hosting this application */
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
"gen": "Microsoft.Framework.CodeGeneration",
"ef": "EntityFramework.Commands"
"ef": "EntityFramework.Commands",
"test": "xunit.runner.aspnet"
},
"frameworks": {
"aspnet50": { },