From e7917f8270981b47669966ed34c2a23f5c1e5d64 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Fri, 17 Nov 2023 07:07:43 -0800 Subject: [PATCH 1/4] Send a MySQL ping packet by default. Fixes #2031 Users can opt in to setting a command that will be executed on the server, but the default is now a more efficient ping. --- .../MySqlHealthCheckBuilderExtensions.cs | 9 ++++---- src/HealthChecks.MySql/MySqlHealthCheck.cs | 23 +++++++++++++------ .../MySqlHealthCheckOptions.cs | 3 +-- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs index 09e2fac106..0b755f37bd 100644 --- a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs @@ -10,14 +10,13 @@ namespace Microsoft.Extensions.DependencyInjection; public static class MySqlHealthCheckBuilderExtensions { private const string NAME = "mysql"; - internal const string HEALTH_QUERY = "SELECT 1;"; /// /// Add a health check for MySQL databases. /// /// The . /// The MySQL connection string to be used. - /// The query to be executed. + /// The optional query to be executed. If this is null, a MySQL "ping" packet will be sent to the server instead of a query. /// An optional action to allow additional MySQL specific configuration. /// The health check name. Optional. If null the type name 'mysql' will be used for the name. /// @@ -30,7 +29,7 @@ public static class MySqlHealthCheckBuilderExtensions public static IHealthChecksBuilder AddMySql( this IHealthChecksBuilder builder, string connectionString, - string healthQuery = HEALTH_QUERY, + string? healthQuery = null, Action? configure = null, string? name = default, HealthStatus? failureStatus = default, @@ -45,7 +44,7 @@ public static IHealthChecksBuilder AddMySql( /// /// The . /// A factory to build the MySQL connection string to use. - /// The query to be executed. + /// The optional query to be executed. If this is null, a MySQL "ping" packet will be sent to the server instead of a query. /// An optional action to allow additional MySQL specific configuration. /// The health check name. Optional. If null the type name 'mysql' will be used for the name. /// @@ -58,7 +57,7 @@ public static IHealthChecksBuilder AddMySql( public static IHealthChecksBuilder AddMySql( this IHealthChecksBuilder builder, Func connectionStringFactory, - string healthQuery = HEALTH_QUERY, + string? healthQuery = null, Action? configure = null, string? name = default, HealthStatus? failureStatus = default, diff --git a/src/HealthChecks.MySql/MySqlHealthCheck.cs b/src/HealthChecks.MySql/MySqlHealthCheck.cs index fb7f433193..8bb4b3b4a7 100644 --- a/src/HealthChecks.MySql/MySqlHealthCheck.cs +++ b/src/HealthChecks.MySql/MySqlHealthCheck.cs @@ -13,7 +13,6 @@ public class MySqlHealthCheck : IHealthCheck public MySqlHealthCheck(MySqlHealthCheckOptions options) { Guard.ThrowIfNull(options.ConnectionString, true); - Guard.ThrowIfNull(options.CommandText, true); _options = options; } @@ -27,13 +26,23 @@ public async Task CheckHealthAsync(HealthCheckContext context _options.Configure?.Invoke(connection); await connection.OpenAsync(cancellationToken).ConfigureAwait(false); - using var command = connection.CreateCommand(); - command.CommandText = _options.CommandText; - object? result = await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); + if (_options.CommandText is { } commandText) + { + using var command = connection.CreateCommand(); + command.CommandText = _options.CommandText; + object? result = await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); - return _options.HealthCheckResultBuilder == null - ? HealthCheckResult.Healthy() - : _options.HealthCheckResultBuilder(result); + return _options.HealthCheckResultBuilder == null + ? HealthCheckResult.Healthy() + : _options.HealthCheckResultBuilder(result); + } + else + { + var success = await connection.PingAsync(cancellationToken).ConfigureAwait(false); + return _options.HealthCheckResultBuilder is null + ? (success ? HealthCheckResult.Healthy() : new HealthCheckResult(context.Registration.FailureStatus)) : + _options.HealthCheckResultBuilder(success); + } } catch (Exception ex) { diff --git a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs index d8a1f073d7..47d2629620 100644 --- a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs +++ b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using MySqlConnector; @@ -17,7 +16,7 @@ public class MySqlHealthCheckOptions /// /// The query to be executed. /// - public string CommandText { get; set; } = MySqlHealthCheckBuilderExtensions.HEALTH_QUERY; + public string? CommandText { get; set; } /// /// An optional action executed before the connection is opened in the health check. From e58c2622bbbec1124cdd7ac63980b64436cce238 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Sat, 18 Nov 2023 08:23:55 -0800 Subject: [PATCH 2/4] Add AddMySql overload for MySqlDataSource. This pushes users towards good defaults: firstly registering a MySqlDataSource as a singleton in DI, then just calling .AddHealthChecks().AddMySql() with no other arguments to retrieve and use that same data source for health checks. --- .../MySqlHealthCheckBuilderExtensions.cs | 38 +++++++++++++++++++ .../HealthChecks.MySql.csproj | 2 +- src/HealthChecks.MySql/MySqlHealthCheck.cs | 10 ++++- .../MySqlHealthCheckOptions.cs | 9 ++++- .../DependencyInjection/RegistrationTests.cs | 21 ++++++++++ .../Functional/MySqlHealthCheckTests.cs | 30 ++++++++++++++- .../HealthChecks.MySql.Tests.csproj | 4 ++ 7 files changed, 108 insertions(+), 6 deletions(-) diff --git a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs index 0b755f37bd..5bdab0a805 100644 --- a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs @@ -11,6 +11,44 @@ public static class MySqlHealthCheckBuilderExtensions { private const string NAME = "mysql"; + /// + /// Add a health check for MySQL databases. + /// + /// The . + /// An optional factory to create the . By default, one will be retrieved from the service collection. + /// The optional query to be executed. If this is null, a MySQL "ping" packet will be sent to the server instead of a query. + /// An optional action to allow additional MySQL specific configuration. + /// The health check name. Optional. If null the type name 'mysql' will be used for the name. + /// + /// The that should be reported when the health check fails. Optional. If null then + /// the default status of will be reported. + /// + /// A list of tags that can be used to filter sets of health checks. Optional. + /// An optional representing the timeout of the check. + /// The specified . + public static IHealthChecksBuilder AddMySql( + this IHealthChecksBuilder builder, + Func? dataSourceFactory = null, + string? healthQuery = null, + Action? configure = null, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + name ?? NAME, + sp => new MySqlHealthCheck(new() + { + DataSource = dataSourceFactory?.Invoke(sp) ?? sp.GetRequiredService(), + CommandText = healthQuery, + Configure = configure, + }), + failureStatus, + tags, + timeout)); + } + /// /// Add a health check for MySQL databases. /// diff --git a/src/HealthChecks.MySql/HealthChecks.MySql.csproj b/src/HealthChecks.MySql/HealthChecks.MySql.csproj index b668dd5c0c..d2e059ebf3 100644 --- a/src/HealthChecks.MySql/HealthChecks.MySql.csproj +++ b/src/HealthChecks.MySql/HealthChecks.MySql.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/HealthChecks.MySql/MySqlHealthCheck.cs b/src/HealthChecks.MySql/MySqlHealthCheck.cs index 8bb4b3b4a7..e12009cb2d 100644 --- a/src/HealthChecks.MySql/MySqlHealthCheck.cs +++ b/src/HealthChecks.MySql/MySqlHealthCheck.cs @@ -12,7 +12,11 @@ public class MySqlHealthCheck : IHealthCheck public MySqlHealthCheck(MySqlHealthCheckOptions options) { - Guard.ThrowIfNull(options.ConnectionString, true); + Guard.ThrowIfNull(options); + if (options.DataSource is null && options.ConnectionString is null) + throw new InvalidOperationException("One of options.DataSource or options.ConnectionString must be specified."); + if (options.DataSource is not null && options.ConnectionString is not null) + throw new InvalidOperationException("Only one of options.DataSource or options.ConnectionString must be specified."); _options = options; } @@ -21,7 +25,9 @@ public async Task CheckHealthAsync(HealthCheckContext context { try { - using var connection = new MySqlConnection(_options.ConnectionString); + using var connection = _options.DataSource is not null ? + _options.DataSource.CreateConnection() : + new MySqlConnection(_options.ConnectionString); _options.Configure?.Invoke(connection); await connection.OpenAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs index 47d2629620..245bd34407 100644 --- a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs +++ b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs @@ -9,9 +9,14 @@ namespace HealthChecks.MySql; public class MySqlHealthCheckOptions { /// - /// The MySQL connection string to be used. + /// The MySQL data source to be used. This is the preferred way to specify the MySQL server to be checked. /// - public string ConnectionString { get; set; } = null!; + public MySqlDataSource? DataSource { get; set; } + + /// + /// The MySQL connection string to be used, if isn't set. + /// + public string? ConnectionString { get; set; } /// /// The query to be executed. diff --git a/test/HealthChecks.MySql.Tests/DependencyInjection/RegistrationTests.cs b/test/HealthChecks.MySql.Tests/DependencyInjection/RegistrationTests.cs index 9f3a030da7..15a1627c67 100644 --- a/test/HealthChecks.MySql.Tests/DependencyInjection/RegistrationTests.cs +++ b/test/HealthChecks.MySql.Tests/DependencyInjection/RegistrationTests.cs @@ -1,3 +1,5 @@ +using MySqlConnector; + namespace HealthChecks.MySql.Tests.DependencyInjection; public class mysql_registration_should @@ -18,6 +20,7 @@ public void add_health_check_when_properly_configured() registration.Name.ShouldBe("mysql"); check.ShouldBeOfType(); } + [Fact] public void add_named_health_check_when_properly_configured() { @@ -34,4 +37,22 @@ public void add_named_health_check_when_properly_configured() registration.Name.ShouldBe("my-mysql-group"); check.ShouldBeOfType(); } + + [Fact] + public void add_health_check_for_data_source() + { + var services = new ServiceCollection(); + services + .AddMySqlDataSource("Server=example") + .AddHealthChecks().AddMySql(); + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); + + var registration = options.Value.Registrations.First(); + var check = registration.Factory(serviceProvider); + + registration.Name.ShouldBe("mysql"); + check.ShouldBeOfType(); + } } diff --git a/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs b/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs index 521a396745..dc673aa47d 100644 --- a/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs +++ b/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs @@ -1,11 +1,39 @@ using System.Net; +using MySqlConnector; namespace HealthChecks.MySql.Tests.Functional; public class mysql_healthcheck_should { [Fact] - public async Task be_healthy_when_mysql_server_is_available() + public async Task be_healthy_when_mysql_server_is_available_using_data_source() + { + var connectionString = "server=localhost;port=3306;database=information_schema;uid=root;password=Password12!"; + + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => + { + services + .AddMySqlDataSource(connectionString) + .AddHealthChecks().AddMySql(tags: new string[] { "mysql" }); + }) + .Configure(app => + { + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("mysql") + }); + }); + + using var server = new TestServer(webHostBuilder); + + using var response = await server.CreateRequest("/health").GetAsync().ConfigureAwait(false); + + response.StatusCode.ShouldBe(HttpStatusCode.OK); + } + + [Fact] + public async Task be_healthy_when_mysql_server_is_available_using_connection_string() { var connectionString = "server=localhost;port=3306;database=information_schema;uid=root;password=Password12!"; diff --git a/test/HealthChecks.MySql.Tests/HealthChecks.MySql.Tests.csproj b/test/HealthChecks.MySql.Tests/HealthChecks.MySql.Tests.csproj index 26e587af5f..99fb87a8d5 100644 --- a/test/HealthChecks.MySql.Tests/HealthChecks.MySql.Tests.csproj +++ b/test/HealthChecks.MySql.Tests/HealthChecks.MySql.Tests.csproj @@ -4,6 +4,10 @@ net6.0;net7.0 + + + + From 479d8f0a9fa244442af4276fbb11f57e363c1923 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Thu, 23 Nov 2023 08:47:14 -0800 Subject: [PATCH 3/4] Add package README for HealthChecks.MySql. --- src/HealthChecks.MySql/README.md | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/HealthChecks.MySql/README.md diff --git a/src/HealthChecks.MySql/README.md b/src/HealthChecks.MySql/README.md new file mode 100644 index 0000000000..6ec4a6db88 --- /dev/null +++ b/src/HealthChecks.MySql/README.md @@ -0,0 +1,59 @@ +## MySQL Health Check + +This health check verifies the ability to communicate with a MySQL Server. +It uses the provided [MySqlDataSource](https://mysqlconnector.net/api/mysqlconnector/mysqldatasourcetype/) or a connection string to connect to the server. + +### Defaults + +By default, the `MySqlDataSource` instance is resolved from service provider. +(This should be the same as the instance being used by the application; do not create a new `MySqlDataSource` just for the health check.) +The health check will send a MySQL "ping" packet to the server to verify connectivity. + +```csharp +builder.Services + .AddMySqlDataSource(builder.Configuration.GetConnectionString("mysql")) // using the MySqlConnector.DependencyInjection package + .AddHealthChecks().AddMySql(); +``` + +### Connection String + +You can also specify a connection string directly: + +```csharp +builder.Services.AddHealthChecks().AddMySql(connectionString: "Server=...;User Id=...;Password=..."); +``` + +This can be useful if you're not using `MySqlDataSource` in your application. + +### Customization + +You can additionally add the following parameters: + +- `healthQuery`: A query to run against the server. If `null` (the default), the health check will send a MySQL "ping" packet to the server. +- `configure`: An action to configure the `MySqlConnection` object. This is called after the `MySqlConnection` is created but before the connection is opened. +- `name`: The health check name. The default is `mysql`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +builder.Services + .AddMySqlDataSource(builder.Configuration.GetConnectionString("mysql")) + .AddHealthChecks().AddMySql( + healthQuery: "SELECT 1;", + configure: conn => conn.ConnectTimeout = 3, + name: "MySQL" + ); +``` + +### Breaking changes + +In previous versions, `MySqlHealthCheck` defaulted to testing connectivity by sending a `SELECT 1;` query to the server. +It has been changed to send a more efficient "ping" packet instead. +To restore the previous behavior, specify `healthQuery: "SELECT 1;"` when registering the health check. + +While not a breaking change, it's now preferred to use `MySqlDataSource` instead of a connection string. +This allows the health check to use the same connection pool as the rest of the application. +This can be achieved by calling the `.AddMySql()` overload that has no required parameters. +The health check assumes that a `MySqlDataSource` instance has been registered with the service provider and will retrieve it automatically. + From f4af1261c9b46967d27e895ebceb496a1ce4268f Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Sat, 9 Dec 2023 08:01:06 -0800 Subject: [PATCH 4/4] Use new MySqlHealthCheckOptions API. There are two constructors: one to initialise with a MySqlDataSource, and one with a connection string. This helps enforce correct uasge of the API by ensuring that exactly one is set. --- .../MySqlHealthCheckBuilderExtensions.cs | 24 +++++------ .../MySqlHealthCheckOptions.cs | 42 +++++++++++++++++-- .../Functional/MySqlHealthCheckTests.cs | 5 +-- .../HealthChecks.MySql.approved.txt | 13 +++--- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs index 5bdab0a805..fc8fcf0fdc 100644 --- a/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.MySql/DependencyInjection/MySqlHealthCheckBuilderExtensions.cs @@ -38,9 +38,8 @@ public static IHealthChecksBuilder AddMySql( { return builder.Add(new HealthCheckRegistration( name ?? NAME, - sp => new MySqlHealthCheck(new() + sp => new MySqlHealthCheck(new(dataSourceFactory?.Invoke(sp) ?? sp.GetRequiredService()) { - DataSource = dataSourceFactory?.Invoke(sp) ?? sp.GetRequiredService(), CommandText = healthQuery, Configure = configure, }), @@ -74,7 +73,13 @@ public static IHealthChecksBuilder AddMySql( IEnumerable? tags = default, TimeSpan? timeout = default) { - return builder.AddMySql(_ => connectionString, healthQuery, configure, name, failureStatus, tags, timeout); + Guard.ThrowIfNull(connectionString, throwOnEmptyString: true); + + return builder.AddMySql(new(connectionString) + { + CommandText = healthQuery, + Configure = configure + }, name, failureStatus, tags, timeout); } /// @@ -106,16 +111,11 @@ public static IHealthChecksBuilder AddMySql( return builder.Add(new HealthCheckRegistration( name ?? NAME, - sp => + sp => new MySqlHealthCheck(new(connectionStringFactory(sp)) { - var options = new MySqlHealthCheckOptions - { - ConnectionString = connectionStringFactory(sp), - CommandText = healthQuery, - Configure = configure, - }; - return new MySqlHealthCheck(options); - }, + CommandText = healthQuery, + Configure = configure, + }), failureStatus, tags, timeout)); diff --git a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs index 245bd34407..a2a15690af 100644 --- a/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs +++ b/src/HealthChecks.MySql/MySqlHealthCheckOptions.cs @@ -7,16 +7,50 @@ namespace HealthChecks.MySql; /// Options for . /// public class MySqlHealthCheckOptions -{ +{ + /// + /// Creates an instance of . + /// + /// The to be used. + /// + /// Depending on how the was configured, the connections it hands out may be pooled. + /// That is why it should be the exact same that is used by other parts of your app. + /// + public MySqlHealthCheckOptions(MySqlDataSource dataSource) + { + DataSource = Guard.ThrowIfNull(dataSource); + } + + /// + /// Creates an instance of . + /// + /// The MySQL connection string to be used. + /// + /// supports additional configuration beyond the connection string, such as logging and naming pools for diagnostics. + /// To specify a data source, use and the constructor. + /// + public MySqlHealthCheckOptions(string connectionString) + { + ConnectionString = Guard.ThrowIfNull(connectionString, throwOnEmptyString: true); + } + /// - /// The MySQL data source to be used. This is the preferred way to specify the MySQL server to be checked. + /// The MySQL data source to be used. /// - public MySqlDataSource? DataSource { get; set; } + /// + /// Depending on how the was configured, the connections it hands out may be pooled. + /// That is why it should be the exact same that is used by other parts of your app. + /// + public MySqlDataSource? DataSource { get; } /// /// The MySQL connection string to be used, if isn't set. /// - public string? ConnectionString { get; set; } + /// + /// supports additional configuration beyond the connection string, such as logging and naming pools for diagnostics. + /// To specify a data source, use and the constructor. + /// + public string? ConnectionString { get; } /// /// The query to be executed. diff --git a/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs b/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs index dc673aa47d..fcaacc83ea 100644 --- a/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs +++ b/test/HealthChecks.MySql.Tests/Functional/MySqlHealthCheckTests.cs @@ -92,10 +92,7 @@ public async Task be_unhealthy_when_mysql_server_is_unavailable_using_options() var webHostBuilder = new WebHostBuilder() .ConfigureServices(services => { - var mysqlOptions = new MySqlHealthCheckOptions - { - ConnectionString = connectionString - }; + var mysqlOptions = new MySqlHealthCheckOptions(connectionString); services.AddHealthChecks() .AddMySql(mysqlOptions, tags: new string[] { "mysql" }); }) diff --git a/test/HealthChecks.MySql.Tests/HealthChecks.MySql.approved.txt b/test/HealthChecks.MySql.Tests/HealthChecks.MySql.approved.txt index f3dfe4a8d5..4dc33b35cd 100644 --- a/test/HealthChecks.MySql.Tests/HealthChecks.MySql.approved.txt +++ b/test/HealthChecks.MySql.Tests/HealthChecks.MySql.approved.txt @@ -7,10 +7,12 @@ namespace HealthChecks.MySql } public class MySqlHealthCheckOptions { - public MySqlHealthCheckOptions() { } - public string CommandText { get; set; } + public MySqlHealthCheckOptions(MySqlConnector.MySqlDataSource dataSource) { } + public MySqlHealthCheckOptions(string connectionString) { } + public string? CommandText { get; set; } public System.Action? Configure { get; set; } - public string ConnectionString { get; set; } + public string? ConnectionString { get; } + public MySqlConnector.MySqlDataSource? DataSource { get; } public System.Func? HealthCheckResultBuilder { get; set; } } } @@ -19,7 +21,8 @@ namespace Microsoft.Extensions.DependencyInjection public static class MySqlHealthCheckBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, HealthChecks.MySql.MySqlHealthCheckOptions options, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func connectionStringFactory, string healthQuery = "SELECT 1;", System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string healthQuery = "SELECT 1;", System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func connectionStringFactory, string? healthQuery = null, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? dataSourceFactory = null, string? healthQuery = null, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddMySql(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? healthQuery = null, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } } } \ No newline at end of file