diff --git a/src/Cli.Tests/ConfigureOptionsTests.cs b/src/Cli.Tests/ConfigureOptionsTests.cs
index 073f349a67..27d9dec08e 100644
--- a/src/Cli.Tests/ConfigureOptionsTests.cs
+++ b/src/Cli.Tests/ConfigureOptionsTests.cs
@@ -926,6 +926,103 @@ public void TestFailureWhenAddingSetSessionContextToMySQLDatabase()
Assert.IsFalse(isSuccess);
}
+ ///
+ /// Tests adding data-source.health.name to a config that doesn't have a health section.
+ /// This method verifies that the health.name can be added to a data source configuration
+ /// that doesn't previously have a health section.
+ /// Command: dab configure --data-source.health.name "My Data Source"
+ ///
+ [TestMethod]
+ public void TestAddDataSourceHealthName()
+ {
+ // Arrange
+ SetupFileSystemWithInitialConfig(INITIAL_CONFIG);
+
+ ConfigureOptions options = new(
+ dataSourceHealthName: "My Data Source",
+ config: TEST_RUNTIME_CONFIG_FILE
+ );
+
+ // Act
+ bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);
+
+ // Assert
+ Assert.IsTrue(isSuccess);
+ string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
+ Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? config));
+ Assert.IsNotNull(config.DataSource);
+ Assert.IsNotNull(config.DataSource.Health);
+ Assert.AreEqual("My Data Source", config.DataSource.Health.Name);
+ Assert.IsTrue(config.DataSource.Health.Enabled); // Default value
+ }
+
+ ///
+ /// Tests updating data-source.health.name on a config that already has a health section.
+ /// This method verifies that the health.name can be updated while preserving other health settings.
+ /// Command: dab configure --data-source.health.name "Updated Name"
+ ///
+ [DataTestMethod]
+ [DataRow("New Name", DisplayName = "Update health name with a simple string")]
+ [DataRow("This is the value", DisplayName = "Update health name with the example from the issue")]
+ public void TestUpdateDataSourceHealthName(string healthName)
+ {
+ // Arrange - Config with existing health section
+ string configWithHealth = @"
+ {
+ ""$schema"": ""test"",
+ ""data-source"": {
+ ""database-type"": ""mssql"",
+ ""connection-string"": ""testconnectionstring"",
+ ""health"": {
+ ""enabled"": false,
+ ""threshold-ms"": 2000
+ }
+ },
+ ""runtime"": {
+ ""rest"": {
+ ""enabled"": true,
+ ""path"": ""/api""
+ },
+ ""graphql"": {
+ ""enabled"": true,
+ ""path"": ""/graphql"",
+ ""allow-introspection"": true
+ },
+ ""host"": {
+ ""mode"": ""development"",
+ ""cors"": {
+ ""origins"": [],
+ ""allow-credentials"": false
+ },
+ ""authentication"": {
+ ""provider"": ""StaticWebApps""
+ }
+ }
+ },
+ ""entities"": {}
+ }";
+ SetupFileSystemWithInitialConfig(configWithHealth);
+
+ ConfigureOptions options = new(
+ dataSourceHealthName: healthName,
+ config: TEST_RUNTIME_CONFIG_FILE
+ );
+
+ // Act
+ bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);
+
+ // Assert
+ Assert.IsTrue(isSuccess);
+ string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
+ Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? config));
+ Assert.IsNotNull(config.DataSource);
+ Assert.IsNotNull(config.DataSource.Health);
+ Assert.AreEqual(healthName, config.DataSource.Health.Name);
+ // Verify existing health settings are preserved
+ Assert.IsFalse(config.DataSource.Health.Enabled);
+ Assert.AreEqual(2000, config.DataSource.Health.ThresholdMs);
+ }
+
///
/// Sets up the mock file system with an initial configuration file.
/// This method adds a config file to the mock file system and verifies its existence.
diff --git a/src/Cli/Commands/ConfigureOptions.cs b/src/Cli/Commands/ConfigureOptions.cs
index 11dca2a4eb..299a791e2d 100644
--- a/src/Cli/Commands/ConfigureOptions.cs
+++ b/src/Cli/Commands/ConfigureOptions.cs
@@ -28,6 +28,7 @@ public ConfigureOptions(
string? dataSourceOptionsContainer = null,
string? dataSourceOptionsSchema = null,
bool? dataSourceOptionsSetSessionContext = null,
+ string? dataSourceHealthName = null,
int? depthLimit = null,
bool? runtimeGraphQLEnabled = null,
string? runtimeGraphQLPath = null,
@@ -80,6 +81,7 @@ public ConfigureOptions(
DataSourceOptionsContainer = dataSourceOptionsContainer;
DataSourceOptionsSchema = dataSourceOptionsSchema;
DataSourceOptionsSetSessionContext = dataSourceOptionsSetSessionContext;
+ DataSourceHealthName = dataSourceHealthName;
// GraphQL
DepthLimit = depthLimit;
RuntimeGraphQLEnabled = runtimeGraphQLEnabled;
@@ -150,6 +152,9 @@ public ConfigureOptions(
[Option("data-source.options.set-session-context", Required = false, HelpText = "Enable session context. Allowed values: true (default), false.")]
public bool? DataSourceOptionsSetSessionContext { get; }
+ [Option("data-source.health.name", Required = false, HelpText = "Identifier for data source in health check report.")]
+ public string? DataSourceHealthName { get; }
+
[Option("runtime.graphql.depth-limit", Required = false, HelpText = "Max allowed depth of the nested query. Allowed values: (0,2147483647] inclusive. Default is infinity. Use -1 to remove limit.")]
public int? DepthLimit { get; }
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index 648edc1950..658a871b53 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -684,6 +684,27 @@ private static bool TryUpdateConfiguredDataSourceOptions(
dbOptions.Add(namingPolicy.ConvertName(nameof(MsSqlOptions.SetSessionContext)), options.DataSourceOptionsSetSessionContext.Value);
}
+ // Handle health.name option
+ if (options.DataSourceHealthName is not null)
+ {
+ // If there's no existing health config, create one with the name
+ // Note: passing enabled: null triggers the base constructor logic that sets Enabled = true
+ if (datasourceHealthCheckConfig is null)
+ {
+ datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(enabled: null, name: options.DataSourceHealthName);
+ }
+ else
+ {
+ // Update the existing health config with the new name while preserving other settings
+ // Preserve threshold only if it was explicitly set by the user
+ int? thresholdToPreserve = datasourceHealthCheckConfig.UserProvidedThresholdMs ? datasourceHealthCheckConfig.ThresholdMs : null;
+ datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(
+ enabled: datasourceHealthCheckConfig.Enabled,
+ name: options.DataSourceHealthName,
+ thresholdMs: thresholdToPreserve);
+ }
+ }
+
dbOptions = EnumerableUtilities.IsNullOrEmpty(dbOptions) ? null : dbOptions;
DataSource dataSource = new(dbType, dataSourceConnectionString, dbOptions, datasourceHealthCheckConfig);
runtimeConfig = runtimeConfig with { DataSource = dataSource };
diff --git a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
index d8286ff7a0..9c08cf4d81 100644
--- a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
+++ b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
@@ -114,7 +114,11 @@ public HealthCheckOptionsConverter(DeserializationVariableReplacementSettings? r
public override void Write(Utf8JsonWriter writer, DatasourceHealthCheckConfig value, JsonSerializerOptions options)
{
- if (value?.UserProvidedEnabled is true)
+ // Write the health object if any of these conditions are met:
+ // - enabled was explicitly provided by the user
+ // - name property has a value
+ // - threshold was explicitly provided by the user
+ if (value?.UserProvidedEnabled is true || value?.Name is not null || value?.UserProvidedThresholdMs is true)
{
writer.WriteStartObject();
writer.WritePropertyName("enabled");