Created
January 16, 2017 16:58
-
-
Save snboisen/df19e7abc9028d23b7a4babab15f85b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using System.Web.Http.Controllers; | |
using System.Web.Http.Filters; | |
using Example.Extensions; | |
namespace Example.Filters | |
{ | |
/// <summary> | |
/// It turns out that request grouping in Application Insights is broken by default when using attribute-based | |
/// routing, since identifiers are included in request names. This filter fixes that by using the route templates | |
/// instead of the URLs. It will not work for requests that never reach the action filter chain however (such as | |
/// requests rejected by the version handler or auth filters). | |
/// </summary> | |
// See: http://apmtips.com/blog/2017/01/12/update-to-the-last-post-set-the-name-in-mvc-web-api/ | |
public class ApplicationInsightsRequestGroupingFilter : IActionFilter | |
{ | |
public Task<HttpResponseMessage> ExecuteActionFilterAsync( | |
HttpActionContext actionContext, | |
CancellationToken cancellationToken, | |
Func<Task<HttpResponseMessage>> continuation) | |
{ | |
var routeData = actionContext.RequestContext.RouteData; | |
var template = routeData.Route.RouteTemplate; | |
if (template != null && template.Length == 0) | |
{ | |
// Root of web service | |
template = "/"; | |
} | |
var requestTelemetry = actionContext.Request.GetHttpContext().GetRequestTelemetry(); | |
// Overwrite name in request telemetry to fix grouping of requests in Application Insights | |
if (template != null && requestTelemetry != null) | |
{ | |
requestTelemetry.Name = template; | |
requestTelemetry.Context.Operation.Name = template; | |
} | |
return continuation(); | |
} | |
public bool AllowMultiple | |
{ | |
get { return false; } | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Net.Http; | |
using System.Web; | |
using Microsoft.ApplicationInsights.DataContracts; | |
namespace Example.Extensions | |
{ | |
public static class HttpRequestMessageExtensions | |
{ | |
private const string HttpContextKey = "MS_HttpContext"; | |
public static HttpContextBase GetHttpContext(this HttpRequestMessage request) | |
{ | |
HttpContextBase context = null; | |
object requestValue; | |
request.Properties.TryGetValue(HttpContextKey, out requestValue); | |
context = requestValue as HttpContextBase; | |
if (context == null) | |
{ | |
PrintDiagnostics(typeof(HttpContextBase), typeof(HttpRequestMessage), HttpContextKey, requestValue); | |
} | |
return context; | |
} | |
/// <summary>Diagnostics: figure out why we could not access context</summary> | |
internal static void PrintDiagnostics(Type typeOfDesiredObject, Type typeOfContainer, string keyOfDesiredObjectInContainer, object valueAtKey) | |
{ | |
string msg; | |
if (valueAtKey == null) | |
{ | |
msg = String.Format("Could not access {0}: no value present in {1} for key {2}", | |
typeOfDesiredObject, typeOfContainer, keyOfDesiredObjectInContainer); | |
} | |
else | |
{ | |
msg = String.Format("Could not access {0}: expected value in {1} for key {2} to be of type {0} but was of type {3}", | |
typeOfDesiredObject, typeOfContainer, keyOfDesiredObjectInContainer, valueAtKey.GetType().FullName); | |
} | |
Trace.WriteLine(msg); | |
} | |
} | |
public static class HttpContextExtensions | |
{ | |
// The AI SDK includes a GetRequestTelemetry extension method so we don't have to know this key, unfortunately | |
// it extends HttpContext and not HttpContextBase/HttpContextWrapper and we cannot access the context inside | |
// the wrapper... | |
// See: https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/294 | |
private const string RequestTelemetryKey = "Microsoft.ApplicationInsights.RequestTelemetry"; | |
public static RequestTelemetry GetRequestTelemetry(this HttpContextBase context) | |
{ | |
RequestTelemetry telemetry = null; | |
object contextValue = null; | |
if (context != null) | |
{ | |
contextValue = context.Items[RequestTelemetryKey]; | |
telemetry = contextValue as RequestTelemetry; | |
} | |
if (telemetry == null) | |
{ | |
HttpRequestMessageExtensions.PrintDiagnostics(typeof(RequestTelemetry), typeof(HttpContextBase), RequestTelemetryKey, contextValue); | |
} | |
return telemetry; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment