diff --git a/src/Cli.Tests/EndToEndTests.cs b/src/Cli.Tests/EndToEndTests.cs index 9648f119c5..745de4fd46 100644 --- a/src/Cli.Tests/EndToEndTests.cs +++ b/src/Cli.Tests/EndToEndTests.cs @@ -3,6 +3,7 @@ using Azure.DataApiBuilder.Config.Converters; using Azure.DataApiBuilder.Product; +using Azure.DataApiBuilder.Service; using Cli.Constants; using Microsoft.Data.SqlClient; @@ -857,6 +858,80 @@ public void TestEngineStartUpWithVerboseAndLogLevelOptions(string logLevelOption StringAssert.Contains(output, $"User provided config file: {TEST_RUNTIME_CONFIG_FILE}", StringComparison.Ordinal); } + /// + /// Validates that `dab start` correctly sets + /// based on whether the --LogLevel CLI flag is provided. + /// + /// When the --LogLevel flag is provided, IsLogLevelOverriddenByCli should be true. + /// When the --LogLevel flag is omitted (log level comes from the config file), IsLogLevelOverriddenByCli should be false. + /// + /// The --LogLevel CLI flag value, or null to omit the flag. + /// Expected value of Startup.IsLogLevelOverriddenByCli. + [DataTestMethod] + [DataRow(null, false, DisplayName = "IsLogLevelOverriddenByCli is false")] + [DataRow(LogLevel.Error, true, DisplayName = "IsLogLevelOverriddenByCli is true")] + public async Task TestStartCommandResolvesLogLevelFromConfigOrFlag( + LogLevel? cliLogLevel, + bool expectedIsOverridden) + { + string baseConfig = @" + { + ""$schema"": """ + DAB_DRAFT_SCHEMA_TEST_PATH + @""", + ""data-source"": { + ""database-type"": ""mssql"", + ""connection-string"": """ + SAMPLE_TEST_CONN_STRING + @""" + }, + ""runtime"": { + ""rest"": { + ""path"": ""/api"", + ""enabled"": true + }, + ""graphql"": { + ""path"": ""/graphql"", + ""enabled"": true, + ""allow-introspection"": true + }, + ""host"": { + ""mode"": ""development"", + ""cors"": { + ""origins"": [], + ""allow-credentials"": false + }, + ""authentication"": { + ""provider"": ""Unauthenticated"" + } + }, + ""telemetry"": { + ""log-level"": { + ""default"": ""Warning"" + } + } + }, + ""entities"": {} + }"; + + // Merge in an entity so the config is not rejected for having an empty entities section. + string configWithLogLevel = AddPropertiesToJson(baseConfig, BASIC_ENTITY_WITH_ANONYMOUS_ROLE); + _fileSystem!.File.WriteAllText(TEST_RUNTIME_CONFIG_FILE, configWithLogLevel); + + StartOptions options = new( + verbose: false, + logLevel: cliLogLevel, + isHttpsRedirectionDisabled: false, + mcpStdio: false, + mcpRole: null, + config: TEST_RUNTIME_CONFIG_FILE); + + // Run TryStartEngineWithOptions on a background task because StartEngine blocks until the host shuts down. + Task engineTask = Task.Run(() => + TryStartEngineWithOptions(options, _runtimeConfigLoader!, _fileSystem!)); + + // Wait for the engine to finish loading the config. + await Task.Delay(TimeSpan.FromSeconds(5)); + + Assert.AreEqual(expectedIsOverridden, Startup.IsLogLevelOverriddenByCli); + } + /// /// Validates that valid usage of verbs and associated options produce exit code 0 (CliReturnCode.SUCCESS). /// Verifies that explicitly implemented verbs (add, update, init, start) and appropriately diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs index c89da760e4..a7eb79ffbd 100644 --- a/src/Cli/ConfigGenerator.cs +++ b/src/Cli/ConfigGenerator.cs @@ -2597,18 +2597,27 @@ public static bool TryStartEngineWithOptions(StartOptions options, FileSystemRun minimumLogLevel = (LogLevel)options.LogLevel; _logger.LogInformation("Setting minimum LogLevel: {minimumLogLevel}.", minimumLogLevel); + args.Add("--LogLevel"); + args.Add(minimumLogLevel.ToString()); } else { minimumLogLevel = deserializedRuntimeConfig.GetConfiguredLogLevel(); HostMode hostModeType = deserializedRuntimeConfig.IsDevelopmentMode() ? HostMode.Development : HostMode.Production; + bool isValueFromDefault = !deserializedRuntimeConfig.IsLogLevelNull() && deserializedRuntimeConfig.Runtime!.Telemetry!.LoggerLevel! + .SingleOrDefault(kvp => kvp.Key.Equals("default", StringComparison.OrdinalIgnoreCase)).Value != null; - _logger.LogInformation($"Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType); + // Check if we set the minimum LogLevel from the config file or if it is based on the host mode. + if (isValueFromDefault) + { + _logger.LogInformation("Using default minimum LogLevel: {minimumLogLevel} from the 'Default' namespace in config file.", minimumLogLevel); + } + else + { + _logger.LogInformation("Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType); + } } - args.Add("--LogLevel"); - args.Add(minimumLogLevel.ToString()); - // This will add args to disable automatic redirects to https if specified by user if (options.IsHttpsRedirectionDisabled) {