diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7be240cc2d..866a2a6714 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
# 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)
diff --git a/Readme.md b/Readme.md
index 97fc0ce2df..80c66a1e9c 100644
--- a/Readme.md
+++ b/Readme.md
@@ -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
=============================================================
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs
index 9a32497f2e..a03f80ea4e 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs
@@ -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;
///
/// Extension methods for that allow adding Application Insights services to application.
@@ -190,8 +192,6 @@ public static IServiceCollection AddApplicationInsightsTelemetry(this IServiceCo
services.AddSingleton();
- services.AddSingleton();
-
services
.TryAddSingleton,
DefaultApplicationInsightsServiceConfigureOptions>();
@@ -201,12 +201,38 @@ public static IServiceCollection AddApplicationInsightsTelemetry(this IServiceCo
// that requires IOptions infrastructure to run and initialize
services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton();
+ services.AddSingleton();
services.AddOptions();
services.AddSingleton, TelemetryConfigurationOptions>();
services.AddSingleton, 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("",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
+ (options => options.Rules.Insert(0,
+ new LoggerFilterRule(
+ "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider", null,
+ LogLevel.Warning, null)));
+ });
+#endif
}
return services;
@@ -406,8 +432,8 @@ internal static void AddTelemetryConfiguration(IConfiguration config,
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));
}
}
}
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerFactoryExtensions.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerFactoryExtensions.cs
index 298b4cdca2..3412418a4d 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerFactoryExtensions.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerFactoryExtensions.cs
@@ -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 @@ public static class ApplicationInsightsLoggerFactoryExtensions
///
///
/// The instance of to use for service resolution.
- [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 @@ public static ILoggerFactory AddApplicationInsights(this ILoggerFactory factory,
///
/// The instance of to use for service resolution.
/// The minimum to be logged
- [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 @@ public static ILoggerFactory AddApplicationInsights(
///
///
/// The instance of to use for service resolution.
- [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 @@ public static ILoggerFactory AddApplicationInsights(
///
/// The instance of to use for service resolution.
/// The callback that gets executed when another ApplicationInsights logger is added.
- [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 filter,
Action loggerAddedCallback)
- {
+ {
+
var client = serviceProvider.GetService();
- var debugLoggerControl = serviceProvider.GetService();
- var options = serviceProvider.GetService>();
+ var debugLoggerControl = serviceProvider.GetService();
+ var options = serviceProvider.GetService>();
if (options == null)
{
- options = Options.Create(new ApplicationInsightsLoggerOptions());
+ options = Options.Create(new Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerOptions());
}
if (debugLoggerControl != null)
@@ -85,8 +86,8 @@ public static ILoggerFactory AddApplicationInsights(
debugLoggerControl.LoggerAdded += loggerAddedCallback;
}
}
-
- factory.AddProvider(new ApplicationInsightsLoggerProvider(client, filter, options));
+ factory.AddProvider(new Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider(client, filter, options));
+
return factory;
}
}
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerProvider.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerProvider.cs
index fe247d8666..08ba8e9d5d 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerProvider.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerProvider.cs
@@ -7,7 +7,10 @@
///
/// implementation that creates returns instances of
///
+#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;
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Microsoft.ApplicationInsights.AspNetCore.csproj b/src/Microsoft.ApplicationInsights.AspNetCore/Microsoft.ApplicationInsights.AspNetCore.csproj
index 07f3488d3b..42c6953bd3 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/Microsoft.ApplicationInsights.AspNetCore.csproj
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/Microsoft.ApplicationInsights.AspNetCore.csproj
@@ -86,17 +86,18 @@
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/TelemetryInitializerBase.cs b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/TelemetryInitializerBase.cs
index cd5fc6d8de..b089b40fec 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/TelemetryInitializerBase.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/TelemetryInitializerBase.cs
@@ -13,11 +13,13 @@ public abstract class TelemetryInitializerBase : ITelemetryInitializer
{
private readonly IHttpContextAccessor httpContextAccessor;
+ ///
public TelemetryInitializerBase(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
+ ///
public void Initialize(ITelemetry telemetry)
{
var context = this.httpContextAccessor.HttpContext;
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebSessionTelemetryInitializer.cs b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebSessionTelemetryInitializer.cs
index b7644b1d0b..debac65f4e 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebSessionTelemetryInitializer.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebSessionTelemetryInitializer.cs
@@ -9,6 +9,7 @@ public class WebSessionTelemetryInitializer : TelemetryInitializerBase
{
private const string WebSessionCookieName = "ai_session";
+ ///
public WebSessionTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
{
diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebUserTelemetryInitializer.cs b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebUserTelemetryInitializer.cs
index eec4ae850a..37c051a776 100644
--- a/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebUserTelemetryInitializer.cs
+++ b/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/WebUserTelemetryInitializer.cs
@@ -5,15 +5,18 @@
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Http;
+ ///
public class WebUserTelemetryInitializer : TelemetryInitializerBase
{
private const string WebUserCookieName = "ai_user";
+ ///
public WebUserTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
{
}
+ ///
protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
{
if (!string.IsNullOrEmpty(telemetry.Context.User.Id))
diff --git a/test/FunctionalTestUtils20/InProcessServer.cs b/test/FunctionalTestUtils20/InProcessServer.cs
index 8493a94e42..f8a9fe2fde 100644
--- a/test/FunctionalTestUtils20/InProcessServer.cs
+++ b/test/FunctionalTestUtils20/InProcessServer.cs
@@ -40,8 +40,9 @@ public class InProcessServer : IDisposable
private TelemetryHttpListenerObservable listener;
private readonly Func configureHost;
+ private readonly Action configureServices;
- public InProcessServer(string assemblyName, ITestOutputHelper output, Func configureHost = null)
+ public InProcessServer(string assemblyName, ITestOutputHelper output, Func configureHost = null, Action configureServices = null)
{
this.output = output;
@@ -49,6 +50,7 @@ public InProcessServer(string assemblyName, ITestOutputHelper output, Func this.configureServices(services));
+ }
+
this.hostingEngine = builder.Build();
this.hostingEngine.Start();
diff --git a/test/MVCFramework20.FunctionalTests/MVCFramework20.FunctionalTests20.csproj b/test/MVCFramework20.FunctionalTests/MVCFramework20.FunctionalTests20.csproj
index dbb25e622b..851b9cef19 100644
--- a/test/MVCFramework20.FunctionalTests/MVCFramework20.FunctionalTests20.csproj
+++ b/test/MVCFramework20.FunctionalTests/MVCFramework20.FunctionalTests20.csproj
@@ -1,4 +1,4 @@
-
+
2.0.0
@@ -56,10 +56,10 @@
-
-
+
+
-
+
diff --git a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs
index 22409f81c2..5c3b4f3f90 100644
--- a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs
+++ b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs
@@ -145,10 +145,10 @@ public static void ConfigurationFactoryMethodUpdatesTheActiveConfigurationSingle
///
/// 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.
///
[Fact]
- public static void DefaultTelemetryconfigurationHasOneTelemetryInitializer()
+ public static void DefaultTelemetryConfigurationHasOneTelemetryInitializer()
{
//
var defaultConfig = TelemetryConfiguration.CreateDefault();
diff --git a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Microsoft.ApplicationInsights.AspNetCore.Tests.csproj b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Microsoft.ApplicationInsights.AspNetCore.Tests.csproj
index 415f277247..e62b415762 100644
--- a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Microsoft.ApplicationInsights.AspNetCore.Tests.csproj
+++ b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Microsoft.ApplicationInsights.AspNetCore.Tests.csproj
@@ -35,15 +35,18 @@
-
-
-
+
+
+
+
+
+
@@ -51,8 +54,8 @@
-
-
+
+
diff --git a/test/WebApi20.FunctionalTests/Controllers/ValuesController.cs b/test/WebApi20.FunctionalTests/Controllers/ValuesController.cs
index 7dfe6c0ec7..626965abfe 100644
--- a/test/WebApi20.FunctionalTests/Controllers/ValuesController.cs
+++ b/test/WebApi20.FunctionalTests/Controllers/ValuesController.cs
@@ -3,12 +3,20 @@
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 logger;
+
+ public ValuesController(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
// GET api/values
[HttpGet]
public IEnumerable Get()
@@ -20,6 +28,10 @@ public IEnumerable Get()
[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";
}
diff --git a/test/WebApi20.FunctionalTests/FunctionalTest/LoggerTests.cs b/test/WebApi20.FunctionalTests/FunctionalTest/LoggerTests.cs
new file mode 100644
index 0000000000..9809af0461
--- /dev/null
+++ b/test/WebApi20.FunctionalTests/FunctionalTest/LoggerTests.cs
@@ -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;
+
+ ///
+ /// 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
+ ///
+ 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>(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("", 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>(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("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>(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 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();
+ }
+ }
+ }
+}
+
diff --git a/test/WebApi20.FunctionalTests/WebApi20.FunctionalTests20.csproj b/test/WebApi20.FunctionalTests/WebApi20.FunctionalTests20.csproj
index 3997872038..ea69a78927 100644
--- a/test/WebApi20.FunctionalTests/WebApi20.FunctionalTests20.csproj
+++ b/test/WebApi20.FunctionalTests/WebApi20.FunctionalTests20.csproj
@@ -35,7 +35,7 @@
-
+