Merge pull request #858 from Microsoft/develop
merge DEVELOP to MASTER (prep 2.7.0-beta3)
This commit is contained in:
Коммит
c9b04f5d2f
|
@ -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
|
||||
|
|
|
@ -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
|
||||
=============================================================
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
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;
|
||||
|
@ -14,7 +16,6 @@
|
|||
using Microsoft.ApplicationInsights.Extensibility.Implementation;
|
||||
using Microsoft.ApplicationInsights.Extensibility.W3C;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DiagnosticAdapter;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
/// <summary>
|
||||
|
@ -38,6 +39,24 @@
|
|||
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>
|
||||
|
@ -72,19 +91,9 @@
|
|||
/// <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())
|
||||
|
@ -176,7 +185,6 @@
|
|||
/// <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());
|
||||
|
@ -185,7 +193,6 @@
|
|||
/// <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)
|
||||
|
@ -282,7 +289,6 @@
|
|||
/// <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)
|
||||
|
@ -294,7 +300,6 @@
|
|||
/// <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);
|
||||
|
@ -310,7 +315,6 @@
|
|||
/// <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);
|
||||
|
@ -319,7 +323,6 @@
|
|||
/// <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);
|
||||
|
@ -559,5 +562,81 @@
|
|||
{
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -15,17 +15,20 @@ namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
|
|||
/// <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))
|
||||
{
|
||||
|
@ -35,19 +38,12 @@ namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
|
|||
}
|
||||
}
|
||||
|
||||
/// <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();
|
||||
|
@ -98,19 +94,40 @@ namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners
|
|||
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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
namespace Microsoft.ApplicationInsights.AspNetCore.DiagnosticListeners.Implementation
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
// see https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
|
||||
/// <summary>
|
||||
/// Efficient implementation of fetching properties of anonymous types with reflection.
|
||||
/// </summary>
|
||||
internal class PropertyFetcher
|
||||
{
|
||||
private readonly string propertyName;
|
||||
private PropertyFetch innerFetcher;
|
||||
|
||||
public PropertyFetcher(string propertyName)
|
||||
{
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public object Fetch(object obj)
|
||||
{
|
||||
if (this.innerFetcher == null)
|
||||
{
|
||||
this.innerFetcher = PropertyFetch.FetcherForProperty(obj.GetType().GetTypeInfo().GetDeclaredProperty(this.propertyName));
|
||||
}
|
||||
|
||||
return this.innerFetcher?.Fetch(obj);
|
||||
}
|
||||
|
||||
private class PropertyFetch
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a property fetcher from a .NET Reflection PropertyInfo class that
|
||||
/// represents a property of a particular type.
|
||||
/// </summary>
|
||||
public static PropertyFetch FetcherForProperty(PropertyInfo propertyInfo)
|
||||
{
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
// returns null on any fetch.
|
||||
return new PropertyFetch();
|
||||
}
|
||||
|
||||
var typedPropertyFetcher = typeof(TypedFetchProperty<,>);
|
||||
var instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
|
||||
propertyInfo.DeclaringType, propertyInfo.PropertyType);
|
||||
return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, propertyInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given an object, fetch the property that this propertyFetch represents.
|
||||
/// </summary>
|
||||
public virtual object Fetch(object obj)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private class TypedFetchProperty<TObject, TProperty> : PropertyFetch
|
||||
{
|
||||
private readonly Func<TObject, TProperty> propertyFetch;
|
||||
|
||||
public TypedFetchProperty(PropertyInfo property)
|
||||
{
|
||||
this.propertyFetch =
|
||||
(Func<TObject, TProperty>)
|
||||
property.GetMethod.CreateDelegate(typeof(Func<TObject, TProperty>));
|
||||
}
|
||||
|
||||
public override object Fetch(object obj)
|
||||
{
|
||||
return this.propertyFetch((TObject)obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,8 +22,10 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IServiceCollection"/> that allow adding Application Insights services to application.
|
||||
|
@ -190,8 +192,6 @@
|
|||
|
||||
services.AddSingleton<TelemetryClient>();
|
||||
|
||||
services.AddSingleton<ApplicationInsightsDebugLogger, ApplicationInsightsDebugLogger>();
|
||||
|
||||
services
|
||||
.TryAddSingleton<IConfigureOptions<ApplicationInsightsServiceOptions>,
|
||||
DefaultApplicationInsightsServiceConfigureOptions>();
|
||||
|
@ -201,12 +201,38 @@
|
|||
// that requires IOptions infrastructure to run and initialize
|
||||
services.AddSingleton<IStartupFilter, ApplicationInsightsStartupFilter>();
|
||||
|
||||
services.AddSingleton<JavaScriptSnippet>();
|
||||
services.AddSingleton<ApplicationInsightsLoggerEvents>();
|
||||
services.AddSingleton<JavaScriptSnippet>();
|
||||
|
||||
services.AddOptions();
|
||||
services.AddSingleton<IOptions<TelemetryConfiguration>, TelemetryConfigurationOptions>();
|
||||
services.AddSingleton<IConfigureOptions<TelemetryConfiguration>, TelemetryConfigurationOptionsSetup>();
|
||||
|
||||
// NetStandard2.0 has a package reference to Microsoft.Extensions.Logging.ApplicationInsights, and
|
||||
// enables ApplicationInsightsLoggerProvider by default.
|
||||
#if NETSTANDARD2_0
|
||||
services.AddLogging(loggingBuilder =>
|
||||
{
|
||||
loggingBuilder.AddApplicationInsights();
|
||||
|
||||
// The default behavior is to capture only logs above Warning level from all categories.
|
||||
// This can achieved with this code level filter -> loggingBuilder.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>("",LogLevel.Warning);
|
||||
// However, this will make it impossible to override this behavior from Configuration like below using appsettings.json:
|
||||
//"ApplicationInsights": {
|
||||
// "LogLevel": {
|
||||
// "": "Error"
|
||||
// }
|
||||
// },
|
||||
// The reason is as both rules will match the filter, the last one added wins.
|
||||
// To ensure that the default filter is in the beginning of filter rules, so that user override from Configuration will always win,
|
||||
// we add code filter rule to the 0th position as below.
|
||||
|
||||
loggingBuilder.Services.Configure<LoggerFilterOptions>
|
||||
(options => options.Rules.Insert(0,
|
||||
new LoggerFilterRule(
|
||||
"Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider", null,
|
||||
LogLevel.Warning, null)));
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
return services;
|
||||
|
@ -406,8 +432,8 @@
|
|||
|
||||
private static bool IsApplicationInsightsAdded(IServiceCollection services)
|
||||
{
|
||||
// We treat ApplicationInsightsDebugLogger as a marker that AI services were added to service collection
|
||||
return services.Any(service => service.ServiceType == typeof(ApplicationInsightsDebugLogger));
|
||||
// We treat TelemetryClient as a marker that AI services were added to service collection
|
||||
return services.Any(service => service.ServiceType == typeof(TelemetryClient));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
exceptionTelemetry.Message = formatter(state, exception);
|
||||
exceptionTelemetry.SeverityLevel = this.GetSeverityLevel(logLevel);
|
||||
exceptionTelemetry.Properties["Exception"] = exception.ToString();
|
||||
exception.Data.Cast<DictionaryEntry>().ToList().ForEach((item) => exceptionTelemetry.Properties[item.Key.ToString()] = item.Value.ToString());
|
||||
exception.Data.Cast<DictionaryEntry>().ToList().ForEach((item) => exceptionTelemetry.Properties[item.Key.ToString()] = (item.Value ?? "null").ToString());
|
||||
PopulateTelemetry(exceptionTelemetry, stateDictionary, eventId);
|
||||
this.telemetryClient.TrackException(exceptionTelemetry);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
using System;
|
||||
using ApplicationInsights;
|
||||
using ApplicationInsights.AspNetCore.Logging;
|
||||
using Microsoft.ApplicationInsights;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="serviceProvider">The instance of <see cref="IServiceProvider"/> to use for service resolution.</param>
|
||||
[Obsolete("Use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package")]
|
||||
[Obsolete("ApplicationInsightsLoggerProvider is now enabled by default when enabling ApplicationInsights monitoring using UseApplicationInsights extension method on IWebHostBuilder or AddApplicationInsightsTelemetry extension method on IServiceCollection. From 2.7.0-beta3 onwards, calling this method will result in double logging and filters applied will not get applied. If interested in using just logging provider, then please use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package. Read more https://aka.ms/ApplicationInsightsILoggerFaq")]
|
||||
public static ILoggerFactory AddApplicationInsights(this ILoggerFactory factory, IServiceProvider serviceProvider)
|
||||
{
|
||||
return factory.AddApplicationInsights(serviceProvider, LogLevel.Warning);
|
||||
|
@ -28,7 +28,7 @@
|
|||
/// <param name="factory"></param>
|
||||
/// <param name="serviceProvider">The instance of <see cref="IServiceProvider"/> to use for service resolution.</param>
|
||||
/// <param name="minLevel">The minimum <see cref="LogLevel"/> to be logged</param>
|
||||
[Obsolete("Use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package")]
|
||||
[Obsolete("ApplicationInsightsLoggerProvider is now enabled by default when enabling ApplicationInsights monitoring using UseApplicationInsights extension method on IWebHostBuilder or AddApplicationInsightsTelemetry extension method on IServiceCollection. From 2.7.0-beta3 onwards, calling this method will result in double logging and filters applied will not get applied. If interested in using just logging provider, then please use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package. Read more https://aka.ms/ApplicationInsightsILoggerFaq")]
|
||||
public static ILoggerFactory AddApplicationInsights(
|
||||
this ILoggerFactory factory,
|
||||
IServiceProvider serviceProvider,
|
||||
|
@ -44,7 +44,7 @@
|
|||
/// <param name="factory"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="serviceProvider">The instance of <see cref="IServiceProvider"/> to use for service resolution.</param>
|
||||
[Obsolete("Use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package")]
|
||||
[Obsolete("ApplicationInsightsLoggerProvider is now enabled by default when enabling ApplicationInsights monitoring using UseApplicationInsights extension method on IWebHostBuilder or AddApplicationInsightsTelemetry extension method on IServiceCollection. From 2.7.0-beta3 onwards, calling this method will result in double logging and filters applied will not get applied. If interested in using just logging provider, then please use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package. Read more https://aka.ms/ApplicationInsightsILoggerFaq")]
|
||||
public static ILoggerFactory AddApplicationInsights(
|
||||
this ILoggerFactory factory,
|
||||
IServiceProvider serviceProvider,
|
||||
|
@ -60,20 +60,21 @@
|
|||
/// <param name="filter"></param>
|
||||
/// <param name="serviceProvider">The instance of <see cref="IServiceProvider"/> to use for service resolution.</param>
|
||||
/// <param name="loggerAddedCallback">The callback that gets executed when another ApplicationInsights logger is added.</param>
|
||||
[Obsolete("Use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package")]
|
||||
[Obsolete("ApplicationInsightsLoggerProvider is now enabled by default when enabling ApplicationInsights monitoring using UseApplicationInsights extension method on IWebHostBuilder or AddApplicationInsightsTelemetry extension method on IServiceCollection. From 2.7.0-beta3 onwards, calling this method will result in double logging and filters applied will not get applied. If interested in using just logging provider, then please use Microsoft.Extensions.Logging.ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights from Microsoft.Extensions.Logging.ApplicationInsights package. Read more https://aka.ms/ApplicationInsightsILoggerFaq")]
|
||||
public static ILoggerFactory AddApplicationInsights(
|
||||
this ILoggerFactory factory,
|
||||
IServiceProvider serviceProvider,
|
||||
Func<string, LogLevel, bool> filter,
|
||||
Action loggerAddedCallback)
|
||||
{
|
||||
{
|
||||
|
||||
var client = serviceProvider.GetService<TelemetryClient>();
|
||||
var debugLoggerControl = serviceProvider.GetService<ApplicationInsightsLoggerEvents>();
|
||||
var options = serviceProvider.GetService<IOptions<ApplicationInsightsLoggerOptions>>();
|
||||
var debugLoggerControl = serviceProvider.GetService<Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerEvents>();
|
||||
var options = serviceProvider.GetService<IOptions<Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerOptions>>();
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
options = Options.Create(new ApplicationInsightsLoggerOptions());
|
||||
options = Options.Create(new Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerOptions());
|
||||
}
|
||||
|
||||
if (debugLoggerControl != null)
|
||||
|
@ -85,8 +86,8 @@
|
|||
debugLoggerControl.LoggerAdded += loggerAddedCallback;
|
||||
}
|
||||
}
|
||||
|
||||
factory.AddProvider(new ApplicationInsightsLoggerProvider(client, filter, options));
|
||||
factory.AddProvider(new Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider(client, filter, options));
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
/// <summary>
|
||||
/// <see cref="ILoggerProvider"/> implementation that creates returns instances of <see cref="ApplicationInsightsLogger"/>
|
||||
/// </summary>
|
||||
#if !NETSTANDARD2_0
|
||||
// For NETSTANDARD2.0 We take dependency on Microsoft.Extensions.Logging.ApplicationInsights which has ApplicationInsightsProvider having the same ProviderAlias and don't want to clash with this ProviderAlias.
|
||||
[ProviderAlias("ApplicationInsights")]
|
||||
#endif
|
||||
internal class ApplicationInsightsLoggerProvider : ILoggerProvider
|
||||
{
|
||||
private readonly TelemetryClient telemetryClient;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Microsoft.ApplicationInsights.AspNetCore</AssemblyName>
|
||||
<VersionPrefix>2.7.0-beta2</VersionPrefix>
|
||||
<VersionPrefix>2.7.0-beta3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>Application Insights for ASP.NET Core Web Applications</AssemblyTitle>
|
||||
|
@ -81,24 +81,23 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.10.0-beta2" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.10.0-beta2" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.10.0-beta2" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer" Version="2.10.0-beta2" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" Version="2.10.0-beta2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.10.0-beta3" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.10.0-beta3" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.10.0-beta3" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer" Version="2.10.0-beta3" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" Version="2.10.0-beta3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.0.2" />
|
||||
<PackageReference Include="System.Text.Encodings.Web" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.0" />
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.9.1" />
|
||||
<PackageReference Include="System.Text.Encodings.Web" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore
|
|||
{
|
||||
if (applicationInsightDiagnosticListener.ListenerName == value.Name)
|
||||
{
|
||||
subs.Add(value.SubscribeWithAdapter(applicationInsightDiagnosticListener));
|
||||
subs.Add(value.Subscribe(applicationInsightDiagnosticListener));
|
||||
applicationInsightDiagnosticListener.OnSubscribe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
{
|
||||
private readonly IHttpContextAccessor httpContextAccessor;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TelemetryInitializerBase(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
this.httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize(ITelemetry telemetry)
|
||||
{
|
||||
var context = this.httpContextAccessor.HttpContext;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
{
|
||||
private const string WebSessionCookieName = "ai_session";
|
||||
|
||||
/// <inheritdoc />
|
||||
public WebSessionTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
|
||||
: base(httpContextAccessor)
|
||||
{
|
||||
|
|
|
@ -5,15 +5,18 @@
|
|||
using Microsoft.ApplicationInsights.DataContracts;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
/// <inheritdoc />
|
||||
public class WebUserTelemetryInitializer : TelemetryInitializerBase
|
||||
{
|
||||
private const string WebUserCookieName = "ai_user";
|
||||
|
||||
/// <inheritdoc />
|
||||
public WebUserTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
|
||||
: base(httpContextAccessor)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(telemetry.Context.User.Id))
|
||||
|
|
|
@ -40,8 +40,9 @@ namespace FunctionalTestUtils
|
|||
|
||||
private TelemetryHttpListenerObservable listener;
|
||||
private readonly Func<IWebHostBuilder, IWebHostBuilder> configureHost;
|
||||
private readonly Action<IServiceCollection> configureServices;
|
||||
|
||||
public InProcessServer(string assemblyName, ITestOutputHelper output, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
|
||||
public InProcessServer(string assemblyName, ITestOutputHelper output, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null, Action<IServiceCollection> configureServices = null)
|
||||
{
|
||||
this.output = output;
|
||||
|
||||
|
@ -49,6 +50,7 @@ namespace FunctionalTestUtils
|
|||
var machineName = "localhost";
|
||||
this.url = "http://" + machineName + ":" + random.Next(5000, 14000).ToString();
|
||||
this.configureHost = configureHost;
|
||||
this.configureServices = configureServices;
|
||||
this.httpListenerConnectionString = LauchApplicationAndStartListener(assemblyName);
|
||||
}
|
||||
|
||||
|
@ -155,7 +157,12 @@ namespace FunctionalTestUtils
|
|||
{
|
||||
builder = this.configureHost(builder);
|
||||
}
|
||||
|
||||
|
||||
if (this.configureServices != null)
|
||||
{
|
||||
builder.ConfigureServices(services => this.configureServices(services));
|
||||
}
|
||||
|
||||
this.hostingEngine = builder.Build();
|
||||
this.hostingEngine.Start();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>2.0.0</VersionPrefix>
|
||||
|
@ -56,10 +56,10 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
|
|
|
@ -145,10 +145,10 @@ namespace Microsoft.Extensions.DependencyInjection.Test
|
|||
|
||||
/// <summary>
|
||||
/// We determine if Active telemtery needs to be configured based on the assumptions that 'default' configuration
|
||||
// created by base SDK has single preset ITelemetryIntitializer. If it ever changes, change TelemetryConfigurationOptions.IsActiveConfigured method as well.
|
||||
// created by base SDK has single preset ITelemetryInitializer. If it ever changes, change TelemetryConfigurationOptions.IsActiveConfigured method as well.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public static void DefaultTelemetryconfigurationHasOneTelemetryInitializer()
|
||||
public static void DefaultTelemetryConfigurationHasOneTelemetryInitializer()
|
||||
{
|
||||
//
|
||||
var defaultConfig = TelemetryConfiguration.CreateDefault();
|
||||
|
|
|
@ -35,15 +35,18 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="1.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||
<PackageReference Include="xunit" Version="2.3.1" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'netcoreapp2.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.0.0" />
|
||||
|
@ -51,8 +54,8 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
@ -107,7 +107,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
@ -127,7 +127,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
@ -149,7 +149,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
@ -173,7 +173,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
@ -194,7 +194,7 @@ namespace Microsoft.ApplicationInsights.AspNetCore.Tests.TelemetryInitializers
|
|||
var contextAccessor = HttpContextAccessorHelper.CreateHttpContextAccessor(new RequestTelemetry(), actionContext);
|
||||
var telemetryListener = new DiagnosticListener(TestListenerName);
|
||||
var initializer = new MvcDiagnosticsListener();
|
||||
telemetryListener.SubscribeWithAdapter(initializer);
|
||||
telemetryListener.Subscribe(initializer);
|
||||
telemetryListener.Write("Microsoft.AspNetCore.Mvc.BeforeAction",
|
||||
new { httpContext = contextAccessor.HttpContext, routeData = actionContext.RouteData });
|
||||
|
||||
|
|
|
@ -3,12 +3,20 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace WebApi20.FunctionalTests.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class ValuesController : Controller
|
||||
{
|
||||
ILogger<ValuesController> logger;
|
||||
|
||||
public ValuesController(ILogger<ValuesController> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
// GET api/values
|
||||
[HttpGet]
|
||||
public IEnumerable<string> Get()
|
||||
|
@ -20,6 +28,10 @@ namespace WebApi20.FunctionalTests.Controllers
|
|||
[HttpGet("{id}")]
|
||||
public string Get(int id)
|
||||
{
|
||||
logger.LogError("error logged");
|
||||
logger.LogWarning("warning logged");
|
||||
logger.LogInformation("information logged");
|
||||
logger.LogTrace("trace logged");
|
||||
return "value";
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
namespace FunctionalTests
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using FunctionalTestUtils;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.ApplicationInsights.DataContracts;
|
||||
using Microsoft.ApplicationInsights.DependencyCollector;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using AI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// These are Functional Tests validating E2E ILogger integration. Though filtering mechanism is done by the ILogger framework itself, we
|
||||
/// are here testing that the integration is done in correct ways.
|
||||
/// Specifically,
|
||||
/// 1. By Default, Warning and above from All categories is expected to captured.
|
||||
/// 2. Any overriding done by user is respected and will override default behaviour
|
||||
/// </summary>
|
||||
public class LoggerTests : TelemetryTestsBase, IDisposable
|
||||
{
|
||||
private const string assemblyName = "WebApi20.FunctionalTests20";
|
||||
public LoggerTests(ITestOutputHelper output) : base (output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestIloggerWarningOrAboveIsCapturedByDefault()
|
||||
{
|
||||
|
||||
#if NETCOREAPP2_0
|
||||
using (var server = new InProcessServer(assemblyName, this.output))
|
||||
{
|
||||
// Make request to this path, which sents one log of each severity Error, Warning, Information, Trace
|
||||
this.ExecuteRequest(server.BaseHost + "/api/values/5");
|
||||
|
||||
// By default, AI is expected to capture Warning, Error
|
||||
var actual = server.Listener.ReceiveItemsOfType<TelemetryItem<MessageData>>(2, TestListenerTimeoutInMs);
|
||||
this.DebugTelemetryItems(actual);
|
||||
|
||||
// Expect 2 items.
|
||||
Assert.Equal(2, actual.Count());
|
||||
|
||||
ValidateMessage(actual[0], new string[] {"error", "warning" });
|
||||
ValidateMessage(actual[1], new string[] { "error", "warning" });
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestIloggerDefaultsCanBeOverridenByUserForAllCategories()
|
||||
{
|
||||
|
||||
#if NETCOREAPP2_0
|
||||
void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// ARRANGE
|
||||
// AddFilter to capture only Error. This is expected to override default behavior.
|
||||
services.AddLogging(builder => builder.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>("", LogLevel.Error));
|
||||
}
|
||||
|
||||
using (var server = new InProcessServer(assemblyName, this.output,null, ConfigureServices))
|
||||
{
|
||||
// Make request to this path, which sents one log of each severity Error, Warning, Information, Trace
|
||||
this.ExecuteRequest(server.BaseHost + "/api/values/5");
|
||||
|
||||
// AI is now expected to capture only Error
|
||||
var actual = server.Listener.ReceiveItemsOfType<TelemetryItem<MessageData>>(1, TestListenerTimeoutInMs);
|
||||
this.DebugTelemetryItems(actual);
|
||||
|
||||
// Expect 1 item1.
|
||||
Assert.Equal(1, actual.Count());
|
||||
|
||||
ValidateMessage(actual[0], new string[] { "error"});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestIloggerDefaultsCanBeOverridenByUserForSpecificCategory()
|
||||
{
|
||||
|
||||
#if NETCOREAPP2_0
|
||||
void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// ARRANGE
|
||||
// AddFilter to capture Trace or above for user category. This is expected to override default behavior.
|
||||
services.AddLogging(builder => builder.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>("WebApi20.FunctionalTests.Controllers", LogLevel.Trace));
|
||||
}
|
||||
|
||||
using (var server = new InProcessServer(assemblyName, this.output, null, ConfigureServices))
|
||||
{
|
||||
// Make request to this path, which sents one log of each severity Error, Warning, Information, Trace
|
||||
this.ExecuteRequest(server.BaseHost + "/api/values/5");
|
||||
|
||||
// AI is now expected to capture Warning or above for all categories (default behavior), except 'WebApi20.FunctionalTests.Controllers' category where Trace of above
|
||||
// is captured. (overridden behavior)
|
||||
var actual = server.Listener.ReceiveItemsOfType<TelemetryItem<MessageData>>(4, TestListenerTimeoutInMs);
|
||||
this.DebugTelemetryItems(actual);
|
||||
|
||||
// Expect 4 items.
|
||||
Assert.Equal(4, actual.Count());
|
||||
|
||||
ValidateMessage(actual[0], new string[] { "error" });
|
||||
ValidateMessage(actual[1], new string[] { "warning" });
|
||||
ValidateMessage(actual[2], new string[] { "information" });
|
||||
ValidateMessage(actual[3], new string[] { "trace" });
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private bool ValidateMessage(Envelope item, string[] expectedMessages)
|
||||
{
|
||||
if (!(item is TelemetryItem<MessageData> trace))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var actualMessage = trace.data.baseData.message;
|
||||
|
||||
bool foundMessage = false;
|
||||
foreach (var msg in expectedMessages)
|
||||
{
|
||||
if(actualMessage.Contains(msg))
|
||||
{
|
||||
foundMessage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return foundMessage;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
while (Activity.Current != null)
|
||||
{
|
||||
Activity.Current.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче