React to logging DI changes (#56)

This commit is contained in:
Pavel Krymets 2017-06-02 08:33:20 -07:00 committed by GitHub
parent 4e30141f30
commit 894a3d9d7a
7 changed files with 58 additions and 147 deletions

View File

@ -79,13 +79,9 @@ namespace IISSample
.Build();
var host = new WebHostBuilder()
.ConfigureLogging((hostingContext, factory) =>
.ConfigureLogging((hostingContext, builder) =>
{
if (hostingContext.Configuration["WIRE_LOGGING_CONFIGURATION"]?.ToLowerInvariant() != "false")
{
factory.UseConfiguration(hostingContext.Configuration.GetSection("Logging"));
}
factory.AddConsole();
builder.AddConsole();
})
.UseKestrel()
.UseStartup<Startup>()

View File

@ -1,72 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup
{
internal class ApplicationInsightsLoggerConfiguration
{
private const string ApplicationInsightsLoggerFactory = "Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider";
private const string ApplicationInsightsLoggerLevelSection = "Logging:" + ApplicationInsightsLoggerFactory + ":LogLevel";
private const string ApplicationInsightsSettingsFile = "ApplicationInsights.settings.json";
private static readonly KeyValuePair<string, LogLevel>[] _defaultLoggingLevels = {
new KeyValuePair<string, LogLevel>("Microsoft", LogLevel.Warning),
new KeyValuePair<string, LogLevel>("System", LogLevel.Warning),
new KeyValuePair<string, LogLevel>(null, LogLevel.Information)
};
public static void ConfigureLogging(IConfigurationBuilder configurationBuilder)
{
// Skip adding default rules when debugger is attached
// we want to send all events to VS
if (!Debugger.IsAttached)
{
configurationBuilder.AddInMemoryCollection(GetDefaultLoggingSettings());
}
var home = Environment.GetEnvironmentVariable("HOME");
if (!string.IsNullOrEmpty(home))
{
var settingsFile = Path.Combine(home, "site", "diagnostics", ApplicationInsightsSettingsFile);
configurationBuilder.AddJsonFile(settingsFile, optional: true);
}
}
public static bool ApplyDefaultFilter(string name, LogLevel level)
{
foreach (var pair in _defaultLoggingLevels)
{
// Default is null
if (pair.Key == null || name.StartsWith(pair.Key, StringComparison.Ordinal))
{
return level >= pair.Value;
}
}
return false;
}
public static bool HasLoggingConfigured(IConfiguration configuration)
{
return configuration?.GetSection(ApplicationInsightsLoggerLevelSection) != null;
}
private static KeyValuePair<string, string>[] GetDefaultLoggingSettings()
{
return _defaultLoggingLevels.Select(pair =>
{
var key = pair.Key ?? "Default";
var optionsKey = $"{ApplicationInsightsLoggerLevelSection}:{key}";
return new KeyValuePair<string, string>(optionsKey, pair.Value.ToString());
}).ToArray();
}
}
}

View File

@ -21,25 +21,12 @@ namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup
var loggerEnabled = true;
Action disableCallback = () => loggerEnabled = false;
if (loggerFactory is LoggerFactory stronglyTypedLoggerFactory &&
ApplicationInsightsLoggerConfiguration.HasLoggingConfigured(stronglyTypedLoggerFactory.Configuration))
{
// We detected that logger settings got to LoggerFactory configuration and
// defaults would be applied
loggerFactory.AddApplicationInsights(
builder.ApplicationServices,
(s, level) => loggerEnabled,
disableCallback);
}
else
{
// It's not AspNetCore LoggerFactory or configuration was not wired
// just add a logger with default settings
loggerFactory.AddApplicationInsights(
builder.ApplicationServices,
(s, level) => loggerEnabled && ApplicationInsightsLoggerConfiguration.ApplyDefaultFilter(s, level),
disableCallback);
}
// We detected that logger settings got to LoggerFactory configuration and
// defaults would be applied
loggerFactory.AddApplicationInsights(
builder.ApplicationServices,
(s, level) => loggerEnabled,
disableCallback);
next(builder);
};

View File

@ -1,9 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
[assembly: HostingStartup(typeof(Microsoft.AspNetCore.ApplicationInsights.HostingStartup.ApplicationInsightsHostingStartup))]
@ -17,6 +25,7 @@ namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup
/// </summary>
public class ApplicationInsightsHostingStartup : IHostingStartup
{
private const string ApplicationInsightsSettingsFile = "ApplicationInsights.settings.json";
/// <summary>
/// Calls UseApplicationInsights
@ -24,7 +33,6 @@ namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup
/// <param name="builder"></param>
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration((context, configurationBuilder) => ApplicationInsightsLoggerConfiguration.ConfigureLogging(configurationBuilder));
builder.UseApplicationInsights();
builder.ConfigureServices(InitializeServices);
@ -37,8 +45,42 @@ namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup
/// <param name="services">The <see cref="IServiceCollection"/> associated with the application.</param>
private void InitializeServices(IServiceCollection services)
{
services.AddSingleton<IConfigureOptions<LoggerFilterOptions>, DefaultApplicationInsightsLoggerFilters>();
services.AddSingleton<IStartupFilter, ApplicationInsightsLoggerStartupFilter>();
services.AddSingleton<ITagHelperComponent, JavaScriptSnippetTagHelperComponent>();
var home = Environment.GetEnvironmentVariable("HOME");
if (!string.IsNullOrEmpty(home))
{
var settingsFile = Path.Combine(home, "site", "diagnostics", ApplicationInsightsSettingsFile);
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile(settingsFile, optional: true);
services.AddLogging(builder => builder.AddConfiguration(configurationBuilder.Build().GetSection("Logging"), replace: true));
}
}
}
internal class DefaultApplicationInsightsLoggerFilters : IConfigureOptions<LoggerFilterOptions>
{
private const string ApplicationInsightsLoggerFactory = "Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider";
private static readonly KeyValuePair<string, LogLevel>[] _defaultLoggingLevels = {
new KeyValuePair<string, LogLevel>("Microsoft", LogLevel.Warning),
new KeyValuePair<string, LogLevel>("System", LogLevel.Warning),
new KeyValuePair<string, LogLevel>(null, LogLevel.Information)
};
public void Configure(LoggerFilterOptions options)
{
foreach (var pair in _defaultLoggingLevels)
{
options.Rules.Add(new LoggerFilterRule(
ApplicationInsightsLoggerFactory,
pair.Key,
null,
(type, name, level) => Debugger.IsAttached || level >= pair.Value
));
}
}
}
}

View File

@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Hosting
throw new ArgumentNullException(nameof(hostBuilder));
}
#pragma warning disable 618
hostBuilder.ConfigureLogging(loggerFactory => loggerFactory.AddAzureWebAppDiagnostics());
hostBuilder.ConfigureLogging(builder => builder.AddAzureWebAppDiagnostics());
#pragma warning restore 618
return hostBuilder;
}

View File

@ -22,25 +22,16 @@ namespace ApplicationInsightsJavaScriptSnippetTest
[InlineData(ApplicationType.Standalone)]
public async Task DefaultAILogFiltersApplied(ApplicationType applicationType)
{
var responseText = await RunRequest(applicationType, "DefaultLogging", true);
var responseText = await RunRequest(applicationType, "DefaultLogging");
AssertDefaultLogs(responseText);
}
[Theory]
[InlineData(ApplicationType.Portable)]
[InlineData(ApplicationType.Standalone)]
public async Task DefaultAILogFiltersAppliedWithoutConfiguration(ApplicationType applicationType)
{
var responseText = await RunRequest(applicationType, "DefaultLogging", false);
AssertDefaultNoConfigurationLogs(responseText);
}
[Theory]
[InlineData(ApplicationType.Portable)]
[InlineData(ApplicationType.Standalone)]
public async Task CustomAILogFiltersApplied(ApplicationType applicationType)
{
var responseText = await RunRequest(applicationType, "CustomLogging", true);
var responseText = await RunRequest(applicationType, "CustomLogging");
AssertCustomLogs(responseText);
}
@ -75,37 +66,6 @@ namespace ApplicationInsightsJavaScriptSnippetTest
Assert.Contains("Specific trace log", responseText);
}
private static void AssertDefaultNoConfigurationLogs(string responseText)
{
// Enabled by default
Assert.Contains("System warning log", responseText);
// Disabled by default
Assert.DoesNotContain("System information log", responseText);
// Disabled by default
Assert.DoesNotContain("System trace log", responseText);
// Enabled by default
Assert.Contains("Microsoft warning log", responseText);
// Disabled by default
Assert.DoesNotContain("Microsoft information log", responseText);
// Disabled by default
Assert.DoesNotContain("Microsoft trace log", responseText);
// Enabled by default
Assert.Contains("Custom warning log", responseText);
// Enabled by default
Assert.Contains("Custom information log", responseText);
// Disabled by default
Assert.DoesNotContain("Custom trace log", responseText);
// Enabled by default
Assert.Contains("Specific warning log", responseText);
// Enabled by default
Assert.Contains("Specific information log", responseText);
// Disabled by default
Assert.DoesNotContain("Specific trace log", responseText);
}
private static void AssertCustomLogs(string responseText)
{
// Custom logger allows only namespaces with 'o' in the name
@ -130,7 +90,7 @@ namespace ApplicationInsightsJavaScriptSnippetTest
Assert.DoesNotContain("Specific trace log", responseText);
}
private async Task<string> RunRequest(ApplicationType applicationType, string environment, bool wireConfiguration)
private async Task<string> RunRequest(ApplicationType applicationType, string environment)
{
string responseText;
var testName = $"ApplicationInsightsLoggingTest_{applicationType}";
@ -153,10 +113,7 @@ namespace ApplicationInsightsJavaScriptSnippetTest
"Microsoft.AspNetCore.ApplicationInsights.HostingStartup"),
new KeyValuePair<string, string>(
"HOME",
Path.Combine(GetApplicationPath(), "home")),
new KeyValuePair<string, string>(
"ASPNETCORE_WIRE_LOGGING_CONFIGURATION",
wireConfiguration.ToString()),
Path.Combine(GetApplicationPath(), "home"))
},
};

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Hosting.Azure.AppServices.Tests
mock.Object.UseAzureAppServices();
mock.Verify(builder => builder.ConfigureLogging(It.IsNotNull<Action<WebHostBuilderContext, LoggerFactory>>()), Times.Once);
mock.Verify(builder => builder.ConfigureServices(It.IsNotNull<Action<IServiceCollection>>()), Times.Once);
}
}
}