diff --git a/src/HealthChecks.Elasticsearch/DependencyInjection/ElasticsearchHealthCheckBuilderExtensions.cs b/src/HealthChecks.Elasticsearch/DependencyInjection/ElasticsearchHealthCheckBuilderExtensions.cs
index 89e8b323c1..be7d3620db 100644
--- a/src/HealthChecks.Elasticsearch/DependencyInjection/ElasticsearchHealthCheckBuilderExtensions.cs
+++ b/src/HealthChecks.Elasticsearch/DependencyInjection/ElasticsearchHealthCheckBuilderExtensions.cs
@@ -33,7 +33,6 @@ public static IHealthChecksBuilder AddElasticsearch(
{
var options = new ElasticsearchOptions();
options.UseServer(elasticsearchUri);
-
return builder.Add(new HealthCheckRegistration(
name ?? NAME,
sp => new ElasticsearchHealthCheck(options),
@@ -68,6 +67,11 @@ public static IHealthChecksBuilder AddElasticsearch(
options.RequestTimeout ??= timeout;
+ if (options.Uri is null && !options.AuthenticateWithElasticCloud)
+ {
+ throw new InvalidOperationException($"there is no server to connect. consider using ${nameof(ElasticsearchOptions.UseElasticCloud)} or ${nameof(ElasticsearchOptions.UseServer)}");
+ }
+
return builder.Add(new HealthCheckRegistration(
name ?? NAME,
sp => new ElasticsearchHealthCheck(options),
@@ -75,4 +79,46 @@ public static IHealthChecksBuilder AddElasticsearch(
tags,
timeout));
}
+
+ ///
+ /// Add a health check for Elasticsearch databases.
+ ///
+ /// The .
+ ///
+ /// An optional factory to obtain instance.
+ /// When not provided, is simply resolved from .
+ /// The health check name. Optional. If null the type name 'elasticsearch' 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 AddElasticsearch(
+ this IHealthChecksBuilder builder,
+ Func? clientFactory = null,
+ string? name = default,
+ HealthStatus? failureStatus = default,
+ IEnumerable? tags = default,
+ TimeSpan? timeout = default)
+ {
+
+ return builder.Add(new HealthCheckRegistration(
+ name ?? NAME,
+ sp =>
+ {
+ ElasticsearchOptions options = new()
+ {
+ RequestTimeout = timeout,
+ Client = clientFactory?.Invoke(sp) ?? sp.GetRequiredService()
+ };
+
+
+ return new ElasticsearchHealthCheck(options);
+ },
+ failureStatus,
+ tags,
+ timeout));
+ }
}
diff --git a/src/HealthChecks.Elasticsearch/ElasticsearchHealthCheck.cs b/src/HealthChecks.Elasticsearch/ElasticsearchHealthCheck.cs
index 10752e1e60..5cf81068b0 100644
--- a/src/HealthChecks.Elasticsearch/ElasticsearchHealthCheck.cs
+++ b/src/HealthChecks.Elasticsearch/ElasticsearchHealthCheck.cs
@@ -1,18 +1,20 @@
using System.Collections.Concurrent;
-using Elasticsearch.Net;
+using System.Diagnostics;
+using Elastic.Clients.Elasticsearch;
+using Elastic.Transport;
using Microsoft.Extensions.Diagnostics.HealthChecks;
-using Nest;
namespace HealthChecks.Elasticsearch;
public class ElasticsearchHealthCheck : IHealthCheck
{
- private static readonly ConcurrentDictionary _connections = new();
+ private static readonly ConcurrentDictionary _connections = new();
private readonly ElasticsearchOptions _options;
public ElasticsearchHealthCheck(ElasticsearchOptions options)
{
+ Debug.Assert(options.Uri is not null || options.Client is not null || options.AuthenticateWithElasticCloud);
_options = Guard.ThrowIfNull(options);
}
@@ -21,60 +23,90 @@ public async Task CheckHealthAsync(HealthCheckContext context
{
try
{
- if (!_connections.TryGetValue(_options.Uri, out var lowLevelClient))
+ ElasticsearchClient? elasticsearchClient = null;
+ if (_options.Client is not null)
{
- var settings = new ConnectionSettings(new Uri(_options.Uri));
+ elasticsearchClient = _options.Client;
+ }
+ else
+ {
+ ElasticsearchClientSettings? settings = null;
+
+ settings = _options.AuthenticateWithElasticCloud
+ ? new ElasticsearchClientSettings(_options.CloudId!, new ApiKey(_options.ApiKey!))
+ : new ElasticsearchClientSettings(new Uri(_options.Uri!));
+
if (_options.RequestTimeout.HasValue)
{
settings = settings.RequestTimeout(_options.RequestTimeout.Value);
}
- if (_options.AuthenticateWithBasicCredentials)
+ if (!_connections.TryGetValue(_options.Uri!, out elasticsearchClient))
{
- settings = settings.BasicAuthentication(_options.UserName, _options.Password);
- }
- else if (_options.AuthenticateWithCertificate)
- {
- settings = settings.ClientCertificate(_options.Certificate);
- }
- else if (_options.AuthenticateWithApiKey)
- {
- settings = settings.ApiKeyAuthentication(_options.ApiKeyAuthenticationCredentials);
- }
- if (_options.CertificateValidationCallback != null)
- {
- settings = settings.ServerCertificateValidationCallback(_options.CertificateValidationCallback);
- }
+ if (_options.AuthenticateWithBasicCredentials)
+ {
+ if (_options.UserName is null)
+ {
+ throw new ArgumentNullException(nameof(_options.UserName));
+ }
+ if (_options.Password is null)
+ {
+ throw new ArgumentNullException(nameof(_options.Password));
+ }
+ settings = settings.Authentication(new BasicAuthentication(_options.UserName, _options.Password));
+ }
+ else if (_options.AuthenticateWithCertificate)
+ {
+ if (_options.Certificate is null)
+ {
+ throw new ArgumentNullException(nameof(_options.Certificate));
+ }
+ settings = settings.ClientCertificate(_options.Certificate);
+ }
+ else if (_options.AuthenticateWithApiKey)
+ {
+ if (_options.ApiKey is null)
+ {
+ throw new ArgumentNullException(nameof(_options.ApiKey));
+ }
+ settings.Authentication(new ApiKey(_options.ApiKey));
+ }
- lowLevelClient = new ElasticClient(settings);
+ if (_options.CertificateValidationCallback != null)
+ {
+ settings = settings.ServerCertificateValidationCallback(_options.CertificateValidationCallback);
+ }
- if (!_connections.TryAdd(_options.Uri, lowLevelClient))
- {
- lowLevelClient = _connections[_options.Uri];
+ elasticsearchClient = new ElasticsearchClient(settings);
+
+ if (!_connections.TryAdd(_options.Uri!, elasticsearchClient))
+ {
+ elasticsearchClient = _connections[_options.Uri!];
+ }
}
}
if (_options.UseClusterHealthApi)
{
- var healthResponse = await lowLevelClient.Cluster.HealthAsync(ct: cancellationToken).ConfigureAwait(false);
+ var healthResponse = await elasticsearchClient.Cluster.HealthAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
- if (healthResponse.ApiCall.HttpStatusCode != 200)
+ if (healthResponse.ApiCallDetails.HttpStatusCode != 200)
{
return new HealthCheckResult(context.Registration.FailureStatus);
}
return healthResponse.Status switch
{
- Health.Green => HealthCheckResult.Healthy(),
- Health.Yellow => HealthCheckResult.Degraded(),
+ Elastic.Clients.Elasticsearch.HealthStatus.Green => HealthCheckResult.Healthy(),
+ Elastic.Clients.Elasticsearch.HealthStatus.Yellow => HealthCheckResult.Degraded(),
_ => new HealthCheckResult(context.Registration.FailureStatus)
};
}
- var pingResult = await lowLevelClient.PingAsync(ct: cancellationToken).ConfigureAwait(false);
- bool isSuccess = pingResult.ApiCall.HttpStatusCode == 200;
+ var pingResult = await elasticsearchClient.PingAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
+ bool isSuccess = pingResult.ApiCallDetails.HttpStatusCode == 200;
return isSuccess
? HealthCheckResult.Healthy()
diff --git a/src/HealthChecks.Elasticsearch/ElasticsearchOptions.cs b/src/HealthChecks.Elasticsearch/ElasticsearchOptions.cs
index 61585104cd..34a144afc4 100644
--- a/src/HealthChecks.Elasticsearch/ElasticsearchOptions.cs
+++ b/src/HealthChecks.Elasticsearch/ElasticsearchOptions.cs
@@ -1,6 +1,6 @@
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
-using Elasticsearch.Net;
+using Elastic.Clients.Elasticsearch;
namespace HealthChecks.Elasticsearch;
@@ -9,15 +9,17 @@ namespace HealthChecks.Elasticsearch;
///
public class ElasticsearchOptions
{
- public string Uri { get; private set; } = null!;
+ public string? Uri { get; private set; }
public string? UserName { get; private set; }
public string? Password { get; private set; }
- public X509Certificate? Certificate { get; private set; }
+ public string? CloudId { get; private set; }
+
+ public string? CloudApiKey { get; private set; }
- public ApiKeyAuthenticationCredentials? ApiKeyAuthenticationCredentials { get; private set; }
+ public X509Certificate? Certificate { get; private set; }
public bool AuthenticateWithBasicCredentials { get; private set; }
@@ -25,20 +27,29 @@ public class ElasticsearchOptions
public bool AuthenticateWithApiKey { get; private set; }
+ public bool AuthenticateWithElasticCloud { get; private set; }
+
public bool UseClusterHealthApi { get; set; }
+ public string? ApiKey { get; private set; }
+
public Func