Skip to content
75 changes: 75 additions & 0 deletions src/Cli.Tests/EndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Azure.DataApiBuilder.Config.Converters;
using Azure.DataApiBuilder.Product;
using Azure.DataApiBuilder.Service;
using Cli.Constants;
using Microsoft.Data.SqlClient;

Expand Down Expand Up @@ -857,6 +858,80 @@ public void TestEngineStartUpWithVerboseAndLogLevelOptions(string logLevelOption
StringAssert.Contains(output, $"User provided config file: {TEST_RUNTIME_CONFIG_FILE}", StringComparison.Ordinal);
}

/// <summary>
/// Validates that `dab start` correctly sets <see cref="Startup.IsLogLevelOverriddenByCli"/>
/// 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.
/// </summary>
/// <param name="cliLogLevel">The --LogLevel CLI flag value, or null to omit the flag.</param>
/// <param name="expectedIsOverridden">Expected value of Startup.IsLogLevelOverriddenByCli.</param>
[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""
Comment thread
RubenCerna2079 marked this conversation as resolved.
}
}
},
""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);
}

Comment thread
RubenCerna2079 marked this conversation as resolved.
/// <summary>
/// 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
Expand Down
17 changes: 13 additions & 4 deletions src/Cli/ConfigGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated
HostMode hostModeType = deserializedRuntimeConfig.IsDevelopmentMode() ? HostMode.Development : HostMode.Production;
bool isValueFromDefault = !deserializedRuntimeConfig.IsLogLevelNull() && deserializedRuntimeConfig.Runtime!.Telemetry!.LoggerLevel!
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated
.SingleOrDefault(kvp => kvp.Key.Equals("default", StringComparison.OrdinalIgnoreCase)).Value != null;
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated

_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.
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated
if (isValueFromDefault)
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated
{
_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);
Comment thread
RubenCerna2079 marked this conversation as resolved.
Outdated
}
}

args.Add("--LogLevel");
args.Add(minimumLogLevel.ToString());

// This will add args to disable automatic redirects to https if specified by user
if (options.IsHttpsRedirectionDisabled)
{
Expand Down