#353,#354 Add telemetry for begin/end request and unhandled exceptions.
This commit is contained in:
parent
10176373c8
commit
6758010e1a
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Tracing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
|
|
@ -82,6 +83,7 @@ namespace Microsoft.AspNet.Hosting.Internal
|
||||||
var logger = _applicationServices.GetRequiredService<ILogger<HostingEngine>>();
|
var logger = _applicationServices.GetRequiredService<ILogger<HostingEngine>>();
|
||||||
var contextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
|
var contextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
|
||||||
var contextAccessor = _applicationServices.GetRequiredService<IHttpContextAccessor>();
|
var contextAccessor = _applicationServices.GetRequiredService<IHttpContextAccessor>();
|
||||||
|
var telemetrySource = _applicationServices.GetRequiredService<TelemetrySource>();
|
||||||
var server = ServerFactory.Start(_serverInstance,
|
var server = ServerFactory.Start(_serverInstance,
|
||||||
async features =>
|
async features =>
|
||||||
{
|
{
|
||||||
|
|
@ -89,10 +91,32 @@ namespace Microsoft.AspNet.Hosting.Internal
|
||||||
httpContext.ApplicationServices = _applicationServices;
|
httpContext.ApplicationServices = _applicationServices;
|
||||||
var requestIdentifier = GetRequestIdentifier(httpContext);
|
var requestIdentifier = GetRequestIdentifier(httpContext);
|
||||||
|
|
||||||
using (logger.BeginScope("Request Id: {RequestId}", requestIdentifier))
|
if (telemetrySource.IsEnabled("Microsoft.AspNet.Hosting.BeginRequest"))
|
||||||
{
|
{
|
||||||
contextAccessor.HttpContext = httpContext;
|
telemetrySource.WriteTelemetry("Microsoft.AspNet.Hosting.BeginRequest", new { httpContext = httpContext });
|
||||||
await application(httpContext);
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (logger.BeginScope("Request Id: {RequestId}", requestIdentifier))
|
||||||
|
{
|
||||||
|
contextAccessor.HttpContext = httpContext;
|
||||||
|
await application(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (telemetrySource.IsEnabled("Microsoft.AspNet.Hosting.UnhandledException"))
|
||||||
|
{
|
||||||
|
telemetrySource.WriteTelemetry("Microsoft.AspNet.Hosting.UnhandledException", new { httpContext = httpContext, exception = ex });
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (telemetrySource.IsEnabled("Microsoft.AspNet.Hosting.EndRequest"))
|
||||||
|
{
|
||||||
|
telemetrySource.WriteTelemetry("Microsoft.AspNet.Hosting.EndRequest", new { httpContext = httpContext });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.Tracing;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Builder;
|
using Microsoft.AspNet.Hosting.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Internal;
|
using Microsoft.AspNet.Hosting.Internal;
|
||||||
|
|
@ -91,6 +92,10 @@ namespace Microsoft.AspNet.Hosting
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
|
||||||
|
var telemetrySource = new TelemetryListener("Microsoft.AspNet");
|
||||||
|
services.AddInstance<TelemetrySource>(telemetrySource);
|
||||||
|
services.AddInstance<TelemetryListener>(telemetrySource);
|
||||||
|
|
||||||
// Conjure up a RequestServices
|
// Conjure up a RequestServices
|
||||||
services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();
|
services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,15 @@
|
||||||
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
||||||
"Microsoft.Framework.Logging": "1.0.0-*",
|
"Microsoft.Framework.Logging": "1.0.0-*",
|
||||||
"Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*",
|
"Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*",
|
||||||
"Newtonsoft.Json": "6.0.6"
|
"Newtonsoft.Json": "6.0.6",
|
||||||
|
"System.Diagnostics.Tracing.Telemetry": "4.0.0-beta-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnx451": { },
|
"dnx451": {
|
||||||
|
"frameworkAssemblies": {
|
||||||
|
"System.Runtime": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"dnxcore50": {
|
"dnxcore50": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Console": "4.0.0-beta-*"
|
"System.Console": "4.0.0-beta-*"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.Tracing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
@ -13,6 +14,7 @@ using Microsoft.AspNet.Http;
|
||||||
using Microsoft.Framework.Configuration;
|
using Microsoft.Framework.Configuration;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.TelemetryAdapter;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.TestHost
|
namespace Microsoft.AspNet.TestHost
|
||||||
|
|
@ -310,6 +312,111 @@ namespace Microsoft.AspNet.TestHost
|
||||||
Assert.Equal("FoundFoo:False", await result.Content.ReadAsStringAsync());
|
Assert.Equal("FoundFoo:False", await result.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task BeginEndTelemetryAvailable()
|
||||||
|
{
|
||||||
|
TelemetryListener telemetryListener = null;
|
||||||
|
var server = TestServer.Create(app =>
|
||||||
|
{
|
||||||
|
telemetryListener = app.ApplicationServices.GetRequiredService<TelemetryListener>();
|
||||||
|
app.Run(context =>
|
||||||
|
{
|
||||||
|
return context.Response.WriteAsync("Hello World");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var listener = new TestTelemetryListener();
|
||||||
|
telemetryListener.SubscribeWithAdapter(listener);
|
||||||
|
var result = await server.CreateClient().GetStringAsync("/path");
|
||||||
|
|
||||||
|
Assert.Equal("Hello World", result);
|
||||||
|
Assert.NotNull(listener.BeginRequest?.HttpContext);
|
||||||
|
Assert.NotNull(listener.EndRequest?.HttpContext);
|
||||||
|
Assert.Null(listener.UnhandledException);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExceptionTelemetryAvailable()
|
||||||
|
{
|
||||||
|
TelemetryListener telemetryListener = null;
|
||||||
|
var server = TestServer.Create(app =>
|
||||||
|
{
|
||||||
|
telemetryListener = app.ApplicationServices.GetRequiredService<TelemetryListener>();
|
||||||
|
app.Run(context =>
|
||||||
|
{
|
||||||
|
throw new Exception("Test exception");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var listener = new TestTelemetryListener();
|
||||||
|
telemetryListener.SubscribeWithAdapter(listener);
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => server.CreateClient().GetAsync("/path"));
|
||||||
|
|
||||||
|
Assert.NotNull(listener.BeginRequest?.HttpContext);
|
||||||
|
Assert.Null(listener.EndRequest?.HttpContext);
|
||||||
|
Assert.NotNull(listener.UnhandledException?.HttpContext);
|
||||||
|
Assert.NotNull(listener.UnhandledException?.Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestTelemetryListener
|
||||||
|
{
|
||||||
|
public class OnBeginRequestEventData
|
||||||
|
{
|
||||||
|
public IProxyHttpContext HttpContext { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnBeginRequestEventData BeginRequest { get; set; }
|
||||||
|
|
||||||
|
[TelemetryName("Microsoft.AspNet.Hosting.BeginRequest")]
|
||||||
|
public virtual void OnBeginRequest(IProxyHttpContext httpContext)
|
||||||
|
{
|
||||||
|
BeginRequest = new OnBeginRequestEventData()
|
||||||
|
{
|
||||||
|
HttpContext = httpContext,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OnEndRequestEventData
|
||||||
|
{
|
||||||
|
public IProxyHttpContext HttpContext { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnEndRequestEventData EndRequest { get; set; }
|
||||||
|
|
||||||
|
[TelemetryName("Microsoft.AspNet.Hosting.EndRequest")]
|
||||||
|
public virtual void OnEndRequest(IProxyHttpContext httpContext)
|
||||||
|
{
|
||||||
|
EndRequest = new OnEndRequestEventData()
|
||||||
|
{
|
||||||
|
HttpContext = httpContext,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OnUnhandledExceptionEventData
|
||||||
|
{
|
||||||
|
public IProxyHttpContext HttpContext { get; set; }
|
||||||
|
public IProxyException Exception { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnUnhandledExceptionEventData UnhandledException { get; set; }
|
||||||
|
|
||||||
|
[TelemetryName("Microsoft.AspNet.Hosting.UnhandledException")]
|
||||||
|
public virtual void OnUnhandledException(IProxyHttpContext httpContext, IProxyException exception)
|
||||||
|
{
|
||||||
|
UnhandledException = new OnUnhandledExceptionEventData()
|
||||||
|
{
|
||||||
|
HttpContext = httpContext,
|
||||||
|
Exception = exception,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IProxyHttpContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IProxyException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public void Configure(IApplicationBuilder builder)
|
public void Configure(IApplicationBuilder builder)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||||
|
"Microsoft.Framework.TelemetryAdapter": "1.0.0-*",
|
||||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue