From f765d9575b6b033e1df10180a4c29bf99a485527 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 31 Oct 2024 10:19:20 -0700 Subject: [PATCH 1/5] Add RestrictHostLogs config --- .../Config/FunctionsHostingConfigOptions.cs | 16 ++++++++++++++++ src/WebJobs.Script/ScriptConstants.cs | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs b/src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs index f389c57cc1..31bf50cbb6 100644 --- a/src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs +++ b/src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs @@ -85,6 +85,22 @@ public bool SwtIssuerEnabled } } + /// + /// Gets or sets a value indicating whether non-critical logs should be disabled in the host. + /// + public bool RestrictHostLogs + { + get + { + return GetFeatureOrDefault(ScriptConstants.HostingConfigRestrictHostLogs, "1") == "1"; + } + + set + { + _features[ScriptConstants.HostingConfigRestrictHostLogs] = value ? "1" : "0"; + } + } + /// /// Gets feature by name. /// diff --git a/src/WebJobs.Script/ScriptConstants.cs b/src/WebJobs.Script/ScriptConstants.cs index 5f0d49e344..ec3c5b9718 100644 --- a/src/WebJobs.Script/ScriptConstants.cs +++ b/src/WebJobs.Script/ScriptConstants.cs @@ -127,6 +127,7 @@ public static class ScriptConstants public const string FeatureFlagEnableHostLogs = "EnableHostLogs"; public const string HostingConfigSwtAuthenticationEnabled = "SwtAuthenticationEnabled"; public const string HostingConfigSwtIssuerEnabled = "SwtIssuerEnabled"; + public const string HostingConfigRestrictHostLogs = "RestrictHostLogs"; public const string SiteAzureFunctionsUriFormat = "https://{0}.azurewebsites.net/azurefunctions"; public const string ScmSiteUriFormat = "https://{0}.scm.azurewebsites.net"; @@ -215,7 +216,7 @@ public static class ScriptConstants public static readonly long DefaultMaxRequestBodySize = 104857600; public static readonly ImmutableArray SystemLogCategoryPrefixes = ImmutableArray.Create("Microsoft.Azure.WebJobs.", "Function.", "Worker.", "Host."); - public static readonly ImmutableArray RestrictedSystemLogCategoryPrefixes = ImmutableArray.Create("Host.Startup"); + public static readonly ImmutableArray RestrictedSystemLogCategoryPrefixes = ImmutableArray.Create("Host.Startup."); public static readonly string FunctionsHostingConfigSectionName = "FunctionsHostingConfig"; public static readonly string MaximumSupportedBundleV3Version = "FunctionRuntimeV3MaxBundleV3Version"; From e65a5a47b11e3f51673762e97bb96cae1b1b933b Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 31 Oct 2024 10:26:38 -0700 Subject: [PATCH 2/5] Utilize RestrictHostLogs flag for logging filters --- .../Diagnostics/ILoggingBuilderExtensions.cs | 4 +-- .../ScriptLoggingBuilderExtensions.cs | 27 ++++++++++++++----- .../ScriptHostBuilderExtensions.cs | 10 ++++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/WebJobs.Script.WebHost/Diagnostics/ILoggingBuilderExtensions.cs b/src/WebJobs.Script.WebHost/Diagnostics/ILoggingBuilderExtensions.cs index 811ccc8854..2f4505a3a0 100644 --- a/src/WebJobs.Script.WebHost/Diagnostics/ILoggingBuilderExtensions.cs +++ b/src/WebJobs.Script.WebHost/Diagnostics/ILoggingBuilderExtensions.cs @@ -8,12 +8,12 @@ namespace Microsoft.Extensions.Logging { public static class ILoggingBuilderExtensions { - public static void AddWebJobsSystem(this ILoggingBuilder builder) where T : SystemLoggerProvider + public static void AddWebJobsSystem(this ILoggingBuilder builder, bool restrictHostLogs = false) where T : SystemLoggerProvider { builder.Services.AddSingleton(); // Log all logs to SystemLogger - builder.AddDefaultWebJobsFilters(LogLevel.Trace); + builder.AddDefaultWebJobsFilters(LogLevel.Trace, restrictHostLogs); } } } diff --git a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs index f1cc8586c5..79b5d8ec54 100644 --- a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs +++ b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs @@ -6,7 +6,6 @@ using System.Linq; using Microsoft.AspNetCore.Hosting; using Microsoft.Azure.WebJobs.Script; -using Microsoft.Azure.WebJobs.Script.Config; using Microsoft.Azure.WebJobs.Script.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; @@ -16,16 +15,24 @@ namespace Microsoft.Extensions.Logging public static class ScriptLoggingBuilderExtensions { private static ConcurrentDictionary _filteredCategoryCache = new ConcurrentDictionary(); + private static ImmutableArray _allowedLogCategoryPrefixes = ScriptConstants.SystemLogCategoryPrefixes; - public static ILoggingBuilder AddDefaultWebJobsFilters(this ILoggingBuilder builder) + // For testing only + internal static ImmutableArray AllowedSystemLogPrefixes => _allowedLogCategoryPrefixes; + + public static ILoggingBuilder AddDefaultWebJobsFilters(this ILoggingBuilder builder, bool restrictHostLogs = false) { + SetSystemLogCategoryPrefixes(restrictHostLogs); + builder.SetMinimumLevel(LogLevel.None); builder.AddFilter((c, l) => Filter(c, l, LogLevel.Information)); return builder; } - public static ILoggingBuilder AddDefaultWebJobsFilters(this ILoggingBuilder builder, LogLevel level) where T : ILoggerProvider + public static ILoggingBuilder AddDefaultWebJobsFilters(this ILoggingBuilder builder, LogLevel level, bool restrictHostLogs = false) where T : ILoggerProvider { + SetSystemLogCategoryPrefixes(restrictHostLogs); + builder.AddFilter(null, LogLevel.None); builder.AddFilter((c, l) => Filter(c, l, level)); return builder; @@ -38,11 +45,17 @@ internal static bool Filter(string category, LogLevel actualLevel, LogLevel minL private static bool IsFiltered(string category) { - ImmutableArray systemLogCategoryPrefixes = FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs) - ? ScriptConstants.SystemLogCategoryPrefixes - : ScriptConstants.RestrictedSystemLogCategoryPrefixes; + return _filteredCategoryCache.GetOrAdd(category, c => _allowedLogCategoryPrefixes.Any(p => c.StartsWith(p))); + } - return _filteredCategoryCache.GetOrAdd(category, c => systemLogCategoryPrefixes.Any(p => category.StartsWith(p))); + private static void SetSystemLogCategoryPrefixes(bool restrictHostLogs) + { + // Once restrictHostLogs is set to true, it stays true for the rest of the application's lifetime + // Set _allowedLogCategoryPrefixes to the restricted prefixes and clear the filter cache + if (restrictHostLogs) + { + _allowedLogCategoryPrefixes = ScriptConstants.RestrictedSystemLogCategoryPrefixes; + } } public static void AddConsoleIfEnabled(this ILoggingBuilder builder, HostBuilderContext context) diff --git a/src/WebJobs.Script/ScriptHostBuilderExtensions.cs b/src/WebJobs.Script/ScriptHostBuilderExtensions.cs index c705b3137d..7c7760ca94 100644 --- a/src/WebJobs.Script/ScriptHostBuilderExtensions.cs +++ b/src/WebJobs.Script/ScriptHostBuilderExtensions.cs @@ -81,7 +81,9 @@ public static IHostBuilder AddScriptHost(this IHostBuilder builder, // Host configuration builder.ConfigureLogging((context, loggingBuilder) => { - loggingBuilder.AddDefaultWebJobsFilters(); + var hostingConfigOptions = applicationOptions.RootServiceProvider.GetService>(); + var restrictHostLogs = RestrictHostLogs(hostingConfigOptions.Value, SystemEnvironment.Instance); + loggingBuilder.AddDefaultWebJobsFilters(restrictHostLogs); string loggingPath = ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "Logging"); loggingBuilder.AddConfiguration(context.Configuration.GetSection(loggingPath)); @@ -492,6 +494,12 @@ private static IDistributedLockManager GetBlobLockManager(IServiceProvider provi } } + private static bool RestrictHostLogs(FunctionsHostingConfigOptions options, IEnvironment environment) + { + // Feature flag should take precedence over the host configuration + return !FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs, environment) && options.RestrictHostLogs; + } + /// /// Gets and removes the specified value, if it exists and is of type T. /// Throws an InvalidOperationException if the key does not exist or is not of type T. From ba722cac30c66abe9df232a49d9e572676d6a503 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 31 Oct 2024 10:53:37 -0700 Subject: [PATCH 3/5] Update tests --- .../TestHostBuilderExtensions.cs | 17 ++++- .../DefaultDependencyValidatorTests.cs | 41 +++++----- .../FunctionsHostingConfigOptionsTest.cs | 33 ++++++-- .../Configuration/RestrictHostLogsTests.cs | 75 +++++++++++++++++++ 4 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs diff --git a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs index a1f55a1442..a6c6894868 100644 --- a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs +++ b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs @@ -29,13 +29,13 @@ namespace Microsoft.WebJobs.Script.Tests { public static class TestHostBuilderExtensions { - public static IHostBuilder ConfigureDefaultTestWebScriptHost(this IHostBuilder builder, Action configure = null, bool runStartupHostedServices = false) + public static IHostBuilder ConfigureDefaultTestWebScriptHost(this IHostBuilder builder, Action configure = null, bool runStartupHostedServices = false, IEnvironment environment = null) { - return builder.ConfigureDefaultTestWebScriptHost(null, configure, runStartupHostedServices); + return builder.ConfigureDefaultTestWebScriptHost(null, configure, runStartupHostedServices, environment: environment); } public static IHostBuilder ConfigureDefaultTestWebScriptHost(this IHostBuilder builder, Action configureWebJobs, - Action configure = null, bool runStartupHostedServices = false, Action configureRootServices = null) + Action configure = null, bool runStartupHostedServices = false, Action configureRootServices = null, IEnvironment environment = null) { var webHostOptions = new ScriptApplicationHostOptions() { @@ -48,9 +48,18 @@ public static IHostBuilder ConfigureDefaultTestWebScriptHost(this IHostBuilder b // Register root services var services = new ServiceCollection(); + + if (environment is not null) + { + services.AddSingleton(environment); + } + else + { + AddMockedSingleton(services); + } + AddMockedSingleton(services); AddMockedSingleton(services); - AddMockedSingleton(services); AddMockedSingleton(services); AddMockedSingleton(services); AddMockedSingleton(services); diff --git a/test/WebJobs.Script.Tests/Configuration/DefaultDependencyValidatorTests.cs b/test/WebJobs.Script.Tests/Configuration/DefaultDependencyValidatorTests.cs index 8bfda63aab..e9fa0f9422 100644 --- a/test/WebJobs.Script.Tests/Configuration/DefaultDependencyValidatorTests.cs +++ b/test/WebJobs.Script.Tests/Configuration/DefaultDependencyValidatorTests.cs @@ -36,27 +36,28 @@ public async Task Validator_AllValid() [Fact] public async Task Validator_InvalidServices_LogsError() { - SystemEnvironment.Instance.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableHostLogs); - - LogMessage invalidServicesMessage = await RunTest(configureJobHost: s => + using (new TestScopedEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableHostLogs)) { - s.AddSingleton(); - s.AddSingleton(); - s.AddSingleton(new MyMetricsLogger()); - - // Try removing system logger - var descriptor = s.Single(p => p.ImplementationType == typeof(SystemLoggerProvider)); - s.Remove(descriptor); - }); - - Assert.NotNull(invalidServicesMessage); - - IEnumerable messageLines = invalidServicesMessage.Exception.Message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()); - Assert.Equal(5, messageLines.Count()); - Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyHostedService).AssemblyQualifiedName)); - Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyScriptEventManager).AssemblyQualifiedName)); - Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyMetricsLogger).AssemblyQualifiedName)); - Assert.Contains(messageLines, p => p.StartsWith("[Missing]") && p.EndsWith(typeof(SystemLoggerProvider).AssemblyQualifiedName)); + LogMessage invalidServicesMessage = await RunTest(configureJobHost: s => + { + s.AddSingleton(); + s.AddSingleton(); + s.AddSingleton(new MyMetricsLogger()); + + // Try removing system logger + var descriptor = s.Single(p => p.ImplementationType == typeof(SystemLoggerProvider)); + s.Remove(descriptor); + }); + + Assert.NotNull(invalidServicesMessage); + + IEnumerable messageLines = invalidServicesMessage.Exception.Message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()); + Assert.Equal(5, messageLines.Count()); + Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyHostedService).AssemblyQualifiedName)); + Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyScriptEventManager).AssemblyQualifiedName)); + Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(typeof(MyMetricsLogger).AssemblyQualifiedName)); + Assert.Contains(messageLines, p => p.StartsWith("[Missing]") && p.EndsWith(typeof(SystemLoggerProvider).AssemblyQualifiedName)); + } } [Fact] diff --git a/test/WebJobs.Script.Tests/Configuration/FunctionsHostingConfigOptionsTest.cs b/test/WebJobs.Script.Tests/Configuration/FunctionsHostingConfigOptionsTest.cs index aa72b0fd22..46e4aea5fd 100644 --- a/test/WebJobs.Script.Tests/Configuration/FunctionsHostingConfigOptionsTest.cs +++ b/test/WebJobs.Script.Tests/Configuration/FunctionsHostingConfigOptionsTest.cs @@ -135,14 +135,35 @@ public void SwtIssuerEnabled_ReturnsExpectedValue() Assert.False(options.SwtIssuerEnabled); } - internal static IHostBuilder GetScriptHostBuilder(string fileName, string fileContent) + [Fact] + public void RestrictHostLogs_ReturnsExpectedValue() + { + FunctionsHostingConfigOptions options = new FunctionsHostingConfigOptions(); + + // defaults to true + Assert.True(options.RestrictHostLogs); + + // returns true when explicitly enabled + options.Features[ScriptConstants.HostingConfigRestrictHostLogs] = "1"; + Assert.True(options.RestrictHostLogs); + + // returns false when disabled + options.Features[ScriptConstants.HostingConfigRestrictHostLogs] = "0"; + Assert.False(options.RestrictHostLogs); + } + + internal static IHostBuilder GetScriptHostBuilder(string fileName, string fileContent, IEnvironment environment = null) { if (!string.IsNullOrEmpty(fileContent)) { File.WriteAllText(fileName, fileContent); } - TestEnvironment environment = new TestEnvironment(); + if (environment is null) + { + environment = new TestEnvironment(); + } + environment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsPlatformConfigFilePath, fileName); IHost webHost = new HostBuilder() @@ -161,7 +182,7 @@ internal static IHostBuilder GetScriptHostBuilder(string fileName, string fileCo { services.AddSingleton(); }) - .ConfigureDefaultTestWebScriptHost(null, configureRootServices: (services) => + .ConfigureDefaultTestWebScriptHost(null, environment: environment, configureRootServices: (services) => { services.AddSingleton(webHost.Services.GetService>()); services.AddSingleton(webHost.Services.GetService>()); @@ -170,7 +191,7 @@ internal static IHostBuilder GetScriptHostBuilder(string fileName, string fileCo public class TestService { - public TestService(IOptions options, IOptionsMonitor monitor) + public TestService(IOptions options, IOptionsMonitor monitor) { Options = options; Monitor = monitor; @@ -180,9 +201,9 @@ public TestService(IOptions options, IOpti }); } - public IOptions Options { get; set; } + public IOptions Options { get; set; } - public IOptionsMonitor Monitor { get; set; } + public IOptionsMonitor Monitor { get; set; } } } } diff --git a/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs b/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs new file mode 100644 index 0000000000..e815785b11 --- /dev/null +++ b/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs @@ -0,0 +1,75 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.Azure.WebJobs.Script.Config; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using WebJobs.Script.Tests; +using Xunit; + +namespace Microsoft.Azure.WebJobs.Script.Tests.Configuration +{ + public class RestrictHostLogsTests : IAsyncLifetime + { + public Task InitializeAsync() + { + return Task.CompletedTask; + } + + public Task DisposeAsync() + { + // Reset the static _allowedLogCategoryPrefixes field after each test to the default value + typeof(ScriptLoggingBuilderExtensions) + .GetField("_allowedLogCategoryPrefixes", BindingFlags.Static | BindingFlags.NonPublic) + .SetValue(null, ScriptConstants.SystemLogCategoryPrefixes); + + SystemEnvironment.Instance.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, null); + return Task.CompletedTask; + } + + [Theory] + [InlineData(true, false, true)] // RestrictHostLogs is true, FeatureFlag is not set, should result in **restricted** logs. This is the default behaviour of the host. + [InlineData(false, true, false)] // RestrictHostLogs is false, FeatureFlag is set, should result in unrestricted logs + [InlineData(true, true, false)] // RestrictHostLogs is true, FeatureFlag is set, should result in unrestricted logs + [InlineData(false, false, false)] // RestrictHostLogs is false, FeatureFlag is not set, should result in unrestricted log + public async Task RestirctHostLogs_SetsCorrectSystemLogPrefix(bool restrictHostLogs, bool setFeatureFlag, bool shouldResultInRestrictedSystemLogs) + { + using (TempDirectory tempDir = new TempDirectory()) + { + var environment = SystemEnvironment.Instance; + string fileName = Path.Combine(tempDir.Path, "settings.txt"); + string fileContent = restrictHostLogs ? string.Empty : $"{ScriptConstants.HostingConfigRestrictHostLogs}=false"; + + if (setFeatureFlag) + { + environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableHostLogs); + } + + IHost host = FunctionsHostingConfigOptionsTest.GetScriptHostBuilder(fileName, fileContent, environment).Build(); + var testService = host.Services.GetService(); + + await host.StartAsync(); + await Task.Delay(1000); + + Assert.Equal(restrictHostLogs, testService.Options.Value.RestrictHostLogs); + Assert.Equal(setFeatureFlag, FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs, environment)); + + if (shouldResultInRestrictedSystemLogs) + { + Assert.Equal(ScriptConstants.RestrictedSystemLogCategoryPrefixes, ScriptLoggingBuilderExtensions.AllowedSystemLogPrefixes); + } + else + { + Assert.Equal(ScriptConstants.SystemLogCategoryPrefixes, ScriptLoggingBuilderExtensions.AllowedSystemLogPrefixes); + } + + await host.StopAsync(); + } + } + } +} From 732defdd6dad21b6b4cc9f42de8b662c963e8945 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 31 Oct 2024 14:16:57 -0700 Subject: [PATCH 4/5] Refactor --- .../WebScriptHostBuilderExtension.cs | 12 +++++++++++- .../Extensions/ScriptLoggingBuilderExtensions.cs | 11 +++-------- src/WebJobs.Script/ScriptConstants.cs | 2 +- src/WebJobs.Script/ScriptHostBuilderExtensions.cs | 10 +--------- .../TestHostBuilderExtensions.cs | 2 +- .../Configuration/RestrictHostLogsTests.cs | 14 +++++++------- 6 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs b/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs index 5a0035c753..426674186d 100644 --- a/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs +++ b/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs @@ -75,9 +75,13 @@ public static IHostBuilder AddWebScriptHost(this IHostBuilder builder, IServiceP }) .ConfigureLogging(loggingBuilder => { + var hostingConfigOptions = rootServiceProvider.GetService>(); + var restrictHostLogs = RestrictHostLogs(hostingConfigOptions.Value); + loggingBuilder.Services.AddSingleton(); + loggingBuilder.AddDefaultWebJobsFilters(restrictHostLogs); + loggingBuilder.AddWebJobsSystem(restrictHostLogs); - loggingBuilder.AddWebJobsSystem(); if (environment.IsAzureMonitorEnabled()) { loggingBuilder.Services.AddSingleton(); @@ -170,6 +174,12 @@ private static void ConfigureRegisteredBuilders(TBuilder builder, ISer } } + private static bool RestrictHostLogs(FunctionsHostingConfigOptions options) + { + // Feature flag should take precedence over the host configuration + return !FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs) && options.RestrictHostLogs; + } + /// /// Used internally to register Newtonsoft formatters with our ScriptHost. /// diff --git a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs index 79b5d8ec54..8d48f6b487 100644 --- a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs +++ b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs @@ -14,8 +14,8 @@ namespace Microsoft.Extensions.Logging { public static class ScriptLoggingBuilderExtensions { - private static ConcurrentDictionary _filteredCategoryCache = new ConcurrentDictionary(); - private static ImmutableArray _allowedLogCategoryPrefixes = ScriptConstants.SystemLogCategoryPrefixes; + private static ConcurrentDictionary _filteredCategoryCache = new (); + private static ImmutableArray _allowedLogCategoryPrefixes = new (); // For testing only internal static ImmutableArray AllowedSystemLogPrefixes => _allowedLogCategoryPrefixes; @@ -50,12 +50,7 @@ private static bool IsFiltered(string category) private static void SetSystemLogCategoryPrefixes(bool restrictHostLogs) { - // Once restrictHostLogs is set to true, it stays true for the rest of the application's lifetime - // Set _allowedLogCategoryPrefixes to the restricted prefixes and clear the filter cache - if (restrictHostLogs) - { - _allowedLogCategoryPrefixes = ScriptConstants.RestrictedSystemLogCategoryPrefixes; - } + _allowedLogCategoryPrefixes = restrictHostLogs ? ScriptConstants.RestrictedSystemLogCategoryPrefixes : ScriptConstants.SystemLogCategoryPrefixes; } public static void AddConsoleIfEnabled(this ILoggingBuilder builder, HostBuilderContext context) diff --git a/src/WebJobs.Script/ScriptConstants.cs b/src/WebJobs.Script/ScriptConstants.cs index ec3c5b9718..3b1cebce28 100644 --- a/src/WebJobs.Script/ScriptConstants.cs +++ b/src/WebJobs.Script/ScriptConstants.cs @@ -216,7 +216,7 @@ public static class ScriptConstants public static readonly long DefaultMaxRequestBodySize = 104857600; public static readonly ImmutableArray SystemLogCategoryPrefixes = ImmutableArray.Create("Microsoft.Azure.WebJobs.", "Function.", "Worker.", "Host."); - public static readonly ImmutableArray RestrictedSystemLogCategoryPrefixes = ImmutableArray.Create("Host.Startup."); + public static readonly ImmutableArray RestrictedSystemLogCategoryPrefixes = ImmutableArray.Create("Host.Startup"); public static readonly string FunctionsHostingConfigSectionName = "FunctionsHostingConfig"; public static readonly string MaximumSupportedBundleV3Version = "FunctionRuntimeV3MaxBundleV3Version"; diff --git a/src/WebJobs.Script/ScriptHostBuilderExtensions.cs b/src/WebJobs.Script/ScriptHostBuilderExtensions.cs index 7c7760ca94..c705b3137d 100644 --- a/src/WebJobs.Script/ScriptHostBuilderExtensions.cs +++ b/src/WebJobs.Script/ScriptHostBuilderExtensions.cs @@ -81,9 +81,7 @@ public static IHostBuilder AddScriptHost(this IHostBuilder builder, // Host configuration builder.ConfigureLogging((context, loggingBuilder) => { - var hostingConfigOptions = applicationOptions.RootServiceProvider.GetService>(); - var restrictHostLogs = RestrictHostLogs(hostingConfigOptions.Value, SystemEnvironment.Instance); - loggingBuilder.AddDefaultWebJobsFilters(restrictHostLogs); + loggingBuilder.AddDefaultWebJobsFilters(); string loggingPath = ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "Logging"); loggingBuilder.AddConfiguration(context.Configuration.GetSection(loggingPath)); @@ -494,12 +492,6 @@ private static IDistributedLockManager GetBlobLockManager(IServiceProvider provi } } - private static bool RestrictHostLogs(FunctionsHostingConfigOptions options, IEnvironment environment) - { - // Feature flag should take precedence over the host configuration - return !FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs, environment) && options.RestrictHostLogs; - } - /// /// Gets and removes the specified value, if it exists and is of type T. /// Throws an InvalidOperationException if the key does not exist or is not of type T. diff --git a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs index a6c6894868..24ca6c2f7c 100644 --- a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs +++ b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs @@ -55,7 +55,7 @@ public static IHostBuilder ConfigureDefaultTestWebScriptHost(this IHostBuilder b } else { - AddMockedSingleton(services); + services.AddSingleton(SystemEnvironment.Instance); } AddMockedSingleton(services); diff --git a/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs b/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs index e815785b11..5dce564e7a 100644 --- a/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs +++ b/test/WebJobs.Script.Tests/Configuration/RestrictHostLogsTests.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System; +using System.Collections.Immutable; using System.IO; using System.Reflection; using System.Threading.Tasks; @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging; using WebJobs.Script.Tests; using Xunit; +using static Microsoft.Azure.WebJobs.Script.Tests.Configuration.FunctionsHostingConfigOptionsTest; namespace Microsoft.Azure.WebJobs.Script.Tests.Configuration { @@ -26,7 +27,7 @@ public Task DisposeAsync() // Reset the static _allowedLogCategoryPrefixes field after each test to the default value typeof(ScriptLoggingBuilderExtensions) .GetField("_allowedLogCategoryPrefixes", BindingFlags.Static | BindingFlags.NonPublic) - .SetValue(null, ScriptConstants.SystemLogCategoryPrefixes); + .SetValue(null, default(ImmutableArray)); SystemEnvironment.Instance.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, null); return Task.CompletedTask; @@ -41,23 +42,22 @@ public async Task RestirctHostLogs_SetsCorrectSystemLogPrefix(bool restrictHostL { using (TempDirectory tempDir = new TempDirectory()) { - var environment = SystemEnvironment.Instance; string fileName = Path.Combine(tempDir.Path, "settings.txt"); string fileContent = restrictHostLogs ? string.Empty : $"{ScriptConstants.HostingConfigRestrictHostLogs}=false"; if (setFeatureFlag) { - environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableHostLogs); + SystemEnvironment.Instance.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableHostLogs); } - IHost host = FunctionsHostingConfigOptionsTest.GetScriptHostBuilder(fileName, fileContent, environment).Build(); - var testService = host.Services.GetService(); + IHost host = GetScriptHostBuilder(fileName, fileContent).Build(); + var testService = host.Services.GetService(); await host.StartAsync(); await Task.Delay(1000); Assert.Equal(restrictHostLogs, testService.Options.Value.RestrictHostLogs); - Assert.Equal(setFeatureFlag, FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs, environment)); + Assert.Equal(setFeatureFlag, FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableHostLogs, SystemEnvironment.Instance)); if (shouldResultInRestrictedSystemLogs) { From 290a1b5e36748538587ec0c4b6d3b6af2003149f Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 1 Nov 2024 12:58:19 -0700 Subject: [PATCH 5/5] Remove accidental dup --- src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs | 1 - .../Extensions/ScriptLoggingBuilderExtensions.cs | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs b/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs index 426674186d..d2b4d407fa 100644 --- a/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs +++ b/src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs @@ -79,7 +79,6 @@ public static IHostBuilder AddWebScriptHost(this IHostBuilder builder, IServiceP var restrictHostLogs = RestrictHostLogs(hostingConfigOptions.Value); loggingBuilder.Services.AddSingleton(); - loggingBuilder.AddDefaultWebJobsFilters(restrictHostLogs); loggingBuilder.AddWebJobsSystem(restrictHostLogs); if (environment.IsAzureMonitorEnabled()) diff --git a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs index 8d48f6b487..876c7b2d87 100644 --- a/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs +++ b/src/WebJobs.Script/Extensions/ScriptLoggingBuilderExtensions.cs @@ -50,7 +50,13 @@ private static bool IsFiltered(string category) private static void SetSystemLogCategoryPrefixes(bool restrictHostLogs) { + var previous = _allowedLogCategoryPrefixes; _allowedLogCategoryPrefixes = restrictHostLogs ? ScriptConstants.RestrictedSystemLogCategoryPrefixes : ScriptConstants.SystemLogCategoryPrefixes; + + if (!previous.IsDefault && !previous.SequenceEqual(_allowedLogCategoryPrefixes)) + { + _filteredCategoryCache.Clear(); + } } public static void AddConsoleIfEnabled(this ILoggingBuilder builder, HostBuilderContext context)