Skip to content
This repository has been archived by the owner on Jun 10, 2020. It is now read-only.

Commit

Permalink
Merge pull request #858 from Microsoft/develop
Browse files Browse the repository at this point in the history
merge DEVELOP to MASTER (prep 2.7.0-beta3)
  • Loading branch information
TimothyMothra authored Apr 1, 2019
2 parents 1d90711 + cbbf53d commit c9b04f5
Show file tree
Hide file tree
Showing 23 changed files with 484 additions and 95 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Version 2.7.0-beta3
- [Enables Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider by default. If ApplicationInsightsLoggerProvider was enabled previously using ILoggerFactory extension method, please remove it to prevent duplicate logs.](https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/854)
- [Remove reference to Microsoft.Extensions.DiagnosticAdapter and use DiagnosticSource subscription APIs directly](https://github.com/Microsoft/ApplicationInsights-aspnetcore/pull/852)
- [Fix: NullReferenceException in ApplicationInsightsLogger.Log when exception contains a Data entry with a null value](https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/848)

## Version 2.7.0-beta2
- Added NetStandard2.0 target.
- Updated Web/Base SDK version dependency to 2.10.0-beta2
Expand Down
4 changes: 4 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
- [Microsoft.ApplicationInsights.AspNetCore](https://www.nuget.org/packages/Microsoft.ApplicationInsights.AspNetCore/)
[![Nuget](https://img.shields.io/nuget/vpre/Microsoft.ApplicationInsights.AspNetCore.svg)](https://nuget.org/packages/Microsoft.ApplicationInsights.AspNetCore)

Windows: [![Build Status](https://mseng.visualstudio.com/AppInsights/_apis/build/status/ChuckNorris/AI_ASPNETCore_Develop?branchName=develop)](https://mseng.visualstudio.com/AppInsights/_build/latest?definitionId=3717&branchName=develop)

Linux :[![Build Status](https://mseng.visualstudio.com/AppInsights/_apis/build/status/ChuckNorris/AI-AspNetCoreSDK-develop-linux?branchName=develop)](https://mseng.visualstudio.com/AppInsights/_build/latest?definitionId=6273&branchName=develop)


Microsoft Application Insights for ASP.NET Core applications
=============================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using Extensibility.Implementation.Tracing;
using Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners.Implementation;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.ApplicationInsights.Common;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.Implementation;
using Microsoft.ApplicationInsights.Extensibility.W3C;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DiagnosticAdapter;
using Microsoft.Extensions.Primitives;

/// <summary>
Expand All @@ -38,6 +39,24 @@ internal class HostingDiagnosticListener : IApplicationInsightDiagnosticListener
private static readonly ActiveSubsciptionManager SubscriptionManager = new ActiveSubsciptionManager();
private const string ActivityCreatedByHostingDiagnosticListener = "ActivityCreatedByHostingDiagnosticListener";

#region fetchers

// fetch is unique per event and per property
private readonly PropertyFetcher httpContextFetcherStart = new PropertyFetcher("HttpContext");
private readonly PropertyFetcher httpContextFetcherStop = new PropertyFetcher("HttpContext");
private readonly PropertyFetcher httpContextFetcherBeginRequest = new PropertyFetcher("httpContext");
private readonly PropertyFetcher httpContextFetcherEndRequest = new PropertyFetcher("httpContext");
private readonly PropertyFetcher httpContextFetcherDiagExceptionUnhandled = new PropertyFetcher("httpContext");
private readonly PropertyFetcher httpContextFetcherDiagExceptionHandled = new PropertyFetcher("httpContext");
private readonly PropertyFetcher httpContextFetcherHostingExceptionUnhandled = new PropertyFetcher("httpContext");
private readonly PropertyFetcher exceptionFetcherDiagExceptionUnhandled = new PropertyFetcher("exception");
private readonly PropertyFetcher exceptionFetcherDiagExceptionHandled = new PropertyFetcher("exception");
private readonly PropertyFetcher exceptionFetcherHostingExceptionUnhandled = new PropertyFetcher("exception");

private readonly PropertyFetcher timestampFetcherBeginRequest = new PropertyFetcher("timestamp");
private readonly PropertyFetcher timestampFetcherEndRequest = new PropertyFetcher("timestamp");
#endregion

/// <summary>
/// Initializes a new instance of the <see cref="T:HostingDiagnosticListener"/> class.
/// </summary>
Expand Down Expand Up @@ -72,19 +91,9 @@ public void OnSubscribe()
/// <inheritdoc/>
public string ListenerName { get; } = "Microsoft.AspNetCore";

/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.HttpRequestIn' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn")]
public void OnHttpRequestIn()
{
// do nothing, just enable the diagnostic source
}

/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.HttpRequestIn.Start' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn.Start")]
public void OnHttpRequestInStart(HttpContext httpContext)
{
if (this.client.IsEnabled())
Expand Down Expand Up @@ -176,7 +185,6 @@ public void OnHttpRequestInStart(HttpContext httpContext)
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop")]
public void OnHttpRequestInStop(HttpContext httpContext)
{
EndRequest(httpContext, Stopwatch.GetTimestamp());
Expand All @@ -185,7 +193,6 @@ public void OnHttpRequestInStop(HttpContext httpContext)
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.BeginRequest' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.BeginRequest")]
public void OnBeginRequest(HttpContext httpContext, long timestamp)
{
if (this.client.IsEnabled() && !this.enableNewDiagnosticEvents)
Expand Down Expand Up @@ -282,7 +289,6 @@ public void OnBeginRequest(HttpContext httpContext, long timestamp)
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.EndRequest' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.EndRequest")]
public void OnEndRequest(HttpContext httpContext, long timestamp)
{
if (!this.enableNewDiagnosticEvents)
Expand All @@ -294,7 +300,6 @@ public void OnEndRequest(HttpContext httpContext, long timestamp)
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.UnhandledException' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Hosting.UnhandledException")]
public void OnHostingException(HttpContext httpContext, Exception exception)
{
this.OnException(httpContext, exception);
Expand All @@ -310,7 +315,6 @@ public void OnHostingException(HttpContext httpContext, Exception exception)
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Hosting.HandledException' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Diagnostics.HandledException")]
public void OnDiagnosticsHandledException(HttpContext httpContext, Exception exception)
{
this.OnException(httpContext, exception);
Expand All @@ -319,7 +323,6 @@ public void OnDiagnosticsHandledException(HttpContext httpContext, Exception exc
/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Diagnostics.UnhandledException' event.
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Diagnostics.UnhandledException")]
public void OnDiagnosticsUnhandledException(HttpContext httpContext, Exception exception)
{
this.OnException(httpContext, exception);
Expand Down Expand Up @@ -559,5 +562,81 @@ public void Dispose()
{
SubscriptionManager.Detach(this);
}

public void OnNext(KeyValuePair<string, object> value)
{
HttpContext httpContext = null;
Exception exception = null;
long? timestamp = null;

switch (value.Key)
{
case "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start":
httpContext = this.httpContextFetcherStart.Fetch(value.Value) as HttpContext;
if (httpContext != null)
{
this.OnHttpRequestInStart(httpContext);
}
break;
case "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop":
httpContext = this.httpContextFetcherStop.Fetch(value.Value) as HttpContext;
if (httpContext != null)
{
this.OnHttpRequestInStop(httpContext);
}
break;
case "Microsoft.AspNetCore.Hosting.BeginRequest":
httpContext = this.httpContextFetcherBeginRequest.Fetch(value.Value) as HttpContext;
timestamp = this.timestampFetcherBeginRequest.Fetch(value.Value) as long?;
if (httpContext != null && timestamp.HasValue)
{
this.OnBeginRequest(httpContext, timestamp.Value);
}
break;
case "Microsoft.AspNetCore.Hosting.EndRequest":
httpContext = this.httpContextFetcherEndRequest.Fetch(value.Value) as HttpContext;
timestamp = this.timestampFetcherEndRequest.Fetch(value.Value) as long?;
if (httpContext != null && timestamp.HasValue)
{
this.OnEndRequest(httpContext, timestamp.Value);
}
break;
case "Microsoft.AspNetCore.Diagnostics.UnhandledException":
httpContext = this.httpContextFetcherDiagExceptionUnhandled.Fetch(value.Value) as HttpContext;
exception = this.exceptionFetcherDiagExceptionUnhandled.Fetch(value.Value) as Exception;
if (httpContext != null && exception != null)
{
this.OnDiagnosticsUnhandledException(httpContext, exception);
}
break;
case "Microsoft.AspNetCore.Diagnostics.HandledException":
httpContext = this.httpContextFetcherDiagExceptionHandled.Fetch(value.Value) as HttpContext;
exception = this.exceptionFetcherDiagExceptionHandled.Fetch(value.Value) as Exception;
if (httpContext != null && exception != null)
{
this.OnDiagnosticsHandledException(httpContext, exception);
}
break;
case "Microsoft.AspNetCore.Hosting.UnhandledException":
httpContext = this.httpContextFetcherHostingExceptionUnhandled.Fetch(value.Value) as HttpContext;
exception = this.exceptionFetcherHostingExceptionUnhandled.Fetch(value.Value) as Exception;
if (httpContext != null && exception != null)
{
this.OnHostingException(httpContext, exception);
}
break;
}
}

/// <inheritdoc />
public void OnError(Exception error)
{
}

/// <inheritdoc />
public void OnCompleted()
{
}

}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
{
using System;
using System.Collections.Generic;

/// <summary>
/// Base diagnostic listener type for Application Insight
/// </summary>
internal interface IApplicationInsightDiagnosticListener : IDisposable
internal interface IApplicationInsightDiagnosticListener : IDisposable, IObserver<KeyValuePair<string, object>>
{
/// <summary>
/// Gets a value indicating which listener this instance should be subscribed to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners.Implementation;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DiagnosticAdapter;

/// <summary>
/// <see cref="IApplicationInsightDiagnosticListener"/> implementation that listens for evens specific to AspNetCore Mvc layer
Expand All @@ -15,17 +15,20 @@ public class MvcDiagnosticsListener : IApplicationInsightDiagnosticListener
/// <inheritdoc />
public string ListenerName { get; } = "Microsoft.AspNetCore";

private readonly PropertyFetcher httpContextFetcher = new PropertyFetcher("httpContext");
private readonly PropertyFetcher routeDataFetcher = new PropertyFetcher("routeData");
private readonly PropertyFetcher routeValuesFetcher = new PropertyFetcher("Values");

/// <summary>
/// Diagnostic event handler method for 'Microsoft.AspNetCore.Mvc.BeforeAction' event
/// </summary>
[DiagnosticName("Microsoft.AspNetCore.Mvc.BeforeAction")]
public void OnBeforeAction(HttpContext httpContext, IRouteData routeData)
public void OnBeforeAction(HttpContext httpContext, IDictionary<string, object> routeValues)
{
var telemetry = httpContext.Features.Get<RequestTelemetry>();

if (telemetry != null && string.IsNullOrEmpty(telemetry.Name))
{
string name = this.GetNameFromRouteContext(routeData);
string name = this.GetNameFromRouteContext(routeValues);

if (!string.IsNullOrEmpty(name))
{
Expand All @@ -35,19 +38,12 @@ public void OnBeforeAction(HttpContext httpContext, IRouteData routeData)
}
}

/// <inheritdoc />
public void OnSubscribe()
{
}

private string GetNameFromRouteContext(IRouteData routeData)
private string GetNameFromRouteContext(IDictionary<string, object> routeValues)
{
string name = null;

if (routeData.Values.Count > 0)
if (routeValues.Count > 0)
{
var routeValues = routeData.Values;

object controller;
routeValues.TryGetValue("controller", out controller);
string controllerString = (controller == null) ? string.Empty : controller.ToString();
Expand Down Expand Up @@ -98,19 +94,40 @@ private string GetNameFromRouteContext(IRouteData routeData)
return name;
}

public void Dispose()
/// <inheritdoc />
public void OnSubscribe()
{
}

/// <summary>
/// Proxy interface for <c>RouteData</c> class from Microsoft.AspNetCore.Routing.Abstractions
/// </summary>
public interface IRouteData
/// <inheritdoc />
public void OnNext(KeyValuePair<string, object> value)
{
if (value.Key == "Microsoft.AspNetCore.Mvc.BeforeAction")
{
var context = httpContextFetcher.Fetch(value.Value) as HttpContext;
var routeData = routeDataFetcher.Fetch(value.Value);
var routeValues = routeValuesFetcher.Fetch(routeData) as IDictionary<string, object>;

if (context != null && routeValues != null)
{
this.OnBeforeAction(context, routeValues);
}
}
}

/// <inheritdoc />
public void OnError(Exception error)
{
}

/// <inheritdoc />
public void OnCompleted()
{
}

/// <inheritdoc />
public void Dispose()
{
/// <summary>
/// Gets the set of values produced by routes on the current routing path.
/// </summary>
IDictionary<string, object> Values { get; }
}
}
}
Loading

0 comments on commit c9b04f5

Please sign in to comment.