diff --git a/src/HealthChecks/HealthChecks/src/DefaultHealthCheckService.cs b/src/HealthChecks/HealthChecks/src/DefaultHealthCheckService.cs index 0ae30771794c..e4615d44f379 100644 --- a/src/HealthChecks/HealthChecks/src/DefaultHealthCheckService.cs +++ b/src/HealthChecks/HealthChecks/src/DefaultHealthCheckService.cs @@ -46,7 +46,7 @@ public override async Task CheckHealthAsync( } var totalTime = ValueStopwatch.StartNew(); - HealthCheckProcessingBegin(); + Log.HealthCheckProcessingBegin(_logger); var tasks = new Task[registrations.Count]; var index = 0; @@ -68,7 +68,7 @@ public override async Task CheckHealthAsync( var totalElapsedTime = totalTime.GetElapsedTime(); var report = new HealthReport(entries, totalElapsedTime); - HealthCheckProcessingEnd(report.Status, totalElapsedTime); + Log.HealthCheckProcessingEnd(_logger, report.Status, totalElapsedTime); return report; } @@ -87,7 +87,7 @@ private async Task RunCheckAsync(HealthCheckRegistration regi var stopwatch = ValueStopwatch.StartNew(); var context = new HealthCheckContext { Registration = registration }; - HealthCheckBegin(registration.Name); + Log.HealthCheckBegin(_logger, registration.Name); HealthReportEntry entry; CancellationTokenSource? timeoutCancellationTokenSource = null; @@ -115,8 +115,8 @@ private async Task RunCheckAsync(HealthCheckRegistration regi data: result.Data, tags: registration.Tags); - HealthCheckEnd(registration, entry, duration); - HealthCheckData(registration, entry); + Log.HealthCheckEnd(_logger, registration, entry, duration); + Log.HealthCheckData(_logger, registration, entry); } catch (OperationCanceledException ex) when (!cancellationToken.IsCancellationRequested) { @@ -129,7 +129,7 @@ private async Task RunCheckAsync(HealthCheckRegistration regi data: null, tags: registration.Tags); - HealthCheckError(registration, ex, duration); + Log.HealthCheckError(_logger, registration, ex, duration); } // Allow cancellation to propagate if it's not a timeout. @@ -144,7 +144,7 @@ private async Task RunCheckAsync(HealthCheckRegistration regi data: null, tags: registration.Tags); - HealthCheckError(registration, ex, duration); + Log.HealthCheckError(_logger, registration, ex, duration); } finally @@ -189,75 +189,85 @@ internal static class EventIds public const int HealthCheckErrorId = 104; public const int HealthCheckDataId = 105; - public static readonly EventId HealthCheckProcessingBegin = new EventId(HealthCheckProcessingBeginId, nameof(HealthCheckProcessingBegin)); - public static readonly EventId HealthCheckProcessingEnd = new EventId(HealthCheckProcessingEndId, nameof(HealthCheckProcessingEnd)); - - public static readonly EventId HealthCheckBegin = new EventId(HealthCheckBeginId, nameof(HealthCheckBegin)); - public static readonly EventId HealthCheckEnd = new EventId(HealthCheckEndId, nameof(HealthCheckEnd)); - public static readonly EventId HealthCheckError = new EventId(HealthCheckErrorId, nameof(HealthCheckError)); - public static readonly EventId HealthCheckData = new EventId(HealthCheckDataId, nameof(HealthCheckData)); + // Hard code the event names to avoid breaking changes. Even if the methods are renamed, these hard-coded names shouldn't change. + public const string HealthCheckProcessingBeginName = "HealthCheckProcessingBegin"; + public const string HealthCheckProcessingEndName = "HealthCheckProcessingEnd"; + public const string HealthCheckBeginName = "HealthCheckBegin"; + public const string HealthCheckEndName = "HealthCheckEnd"; + public const string HealthCheckErrorName = "HealthCheckError"; + public const string HealthCheckDataName = "HealthCheckData"; + + public static readonly EventId HealthCheckProcessingBegin = new EventId(HealthCheckProcessingBeginId, HealthCheckProcessingBeginName); + public static readonly EventId HealthCheckProcessingEnd = new EventId(HealthCheckProcessingEndId, HealthCheckProcessingEndName); + public static readonly EventId HealthCheckBegin = new EventId(HealthCheckBeginId, HealthCheckBeginName); + public static readonly EventId HealthCheckEnd = new EventId(HealthCheckEndId, HealthCheckEndName); + public static readonly EventId HealthCheckError = new EventId(HealthCheckErrorId, HealthCheckErrorName); + public static readonly EventId HealthCheckData = new EventId(HealthCheckDataId, HealthCheckDataName); } - [LoggerMessage(EventId = EventIds.HealthCheckProcessingBeginId, Level = LogLevel.Debug, Message = "Running health checks")] - private partial void HealthCheckProcessingBegin(); + private static partial class Log + { + [LoggerMessage(EventIds.HealthCheckProcessingBeginId, LogLevel.Debug, "Running health checks", EventName = EventIds.HealthCheckProcessingBeginName)] + public static partial void HealthCheckProcessingBegin(ILogger logger); - private void HealthCheckProcessingEnd(HealthStatus status, TimeSpan duration) => - HealthCheckProcessingEnd(status, duration.TotalMilliseconds); + public static void HealthCheckProcessingEnd(ILogger logger, HealthStatus status, TimeSpan duration) => + HealthCheckProcessingEnd(logger, status, duration.TotalMilliseconds); - [LoggerMessage(EventId = EventIds.HealthCheckProcessingEndId, Level = LogLevel.Debug, Message = "Health check processing with combined status {HealthStatus} completed after {ElapsedMilliseconds}ms")] - private partial void HealthCheckProcessingEnd(HealthStatus HealthStatus, double ElapsedMilliseconds); + [LoggerMessage(EventIds.HealthCheckProcessingEndId, LogLevel.Debug, "Health check processing with combined status {HealthStatus} completed after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckProcessingEndName)] + private static partial void HealthCheckProcessingEnd(ILogger logger, HealthStatus HealthStatus, double ElapsedMilliseconds); - [LoggerMessage(EventId = EventIds.HealthCheckBeginId, Level = LogLevel.Debug, Message = "Running health check {HealthCheckName}")] - private partial void HealthCheckBegin(string HealthCheckName); + [LoggerMessage(EventIds.HealthCheckBeginId, LogLevel.Debug, "Running health check {HealthCheckName}", EventName = EventIds.HealthCheckBeginName)] + public static partial void HealthCheckBegin(ILogger logger, string HealthCheckName); - // These are separate so they can have different log levels - private const string HealthCheckEndText = "Health check {HealthCheckName} with status {HealthStatus} completed after {ElapsedMilliseconds}ms with message '{HealthCheckDescription}'"; + // These are separate so they can have different log levels + private const string HealthCheckEndText = "Health check {HealthCheckName} with status {HealthStatus} completed after {ElapsedMilliseconds}ms with message '{HealthCheckDescription}'"; #pragma warning disable SYSLIB1006 - [LoggerMessage(EventId = EventIds.HealthCheckEndId, Level = LogLevel.Debug, Message = HealthCheckEndText)] - private partial void HealthCheckEndHealthy(string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription); + [LoggerMessage(EventIds.HealthCheckEndId, LogLevel.Debug, HealthCheckEndText, EventName = EventIds.HealthCheckEndName)] + private static partial void HealthCheckEndHealthy(ILogger logger, string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription); - [LoggerMessage(EventId = EventIds.HealthCheckEndId, Level = LogLevel.Warning, Message = HealthCheckEndText)] - private partial void HealthCheckEndDegraded(string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription); + [LoggerMessage(EventIds.HealthCheckEndId, LogLevel.Warning, HealthCheckEndText, EventName = EventIds.HealthCheckEndName)] + private static partial void HealthCheckEndDegraded(ILogger logger, string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription); - [LoggerMessage(EventId = EventIds.HealthCheckEndId, Level = LogLevel.Error, Message = HealthCheckEndText)] - private partial void HealthCheckEndUnhealthy(string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription, Exception? exception); + [LoggerMessage(EventIds.HealthCheckEndId, LogLevel.Error, HealthCheckEndText, EventName = EventIds.HealthCheckEndName)] + private static partial void HealthCheckEndUnhealthy(ILogger logger, string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription, Exception? exception); #pragma warning restore SYSLIB1006 - private void HealthCheckEnd(HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration) - { - switch (entry.Status) + public static void HealthCheckEnd(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration) { - case HealthStatus.Healthy: - HealthCheckEndHealthy(registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description); - break; + switch (entry.Status) + { + case HealthStatus.Healthy: + HealthCheckEndHealthy(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description); + break; - case HealthStatus.Degraded: - HealthCheckEndDegraded(registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description); - break; + case HealthStatus.Degraded: + HealthCheckEndDegraded(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description); + break; - case HealthStatus.Unhealthy: - HealthCheckEndUnhealthy(registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description, entry.Exception); - break; + case HealthStatus.Unhealthy: + HealthCheckEndUnhealthy(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description, entry.Exception); + break; + } } - } - [LoggerMessage(EventId = EventIds.HealthCheckErrorId, Level = LogLevel.Error, Message = "Health check {HealthCheckName} threw an unhandled exception after {ElapsedMilliseconds}ms")] - private partial void HealthCheckError(string HealthCheckName, double ElapsedMilliseconds, Exception exception); + [LoggerMessage(EventIds.HealthCheckErrorId, LogLevel.Error, "Health check {HealthCheckName} threw an unhandled exception after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckErrorName)] + private static partial void HealthCheckError(ILogger logger, string HealthCheckName, double ElapsedMilliseconds, Exception exception); - private void HealthCheckError(HealthCheckRegistration registration, Exception exception, TimeSpan duration) => - HealthCheckError(registration.Name, duration.TotalMilliseconds, exception); + public static void HealthCheckError(ILogger logger, HealthCheckRegistration registration, Exception exception, TimeSpan duration) => + HealthCheckError(logger, registration.Name, duration.TotalMilliseconds, exception); - private void HealthCheckData(HealthCheckRegistration registration, HealthReportEntry entry) - { - if (entry.Data.Count > 0 && _logger.IsEnabled(LogLevel.Debug)) + public static void HealthCheckData(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry) { - _logger.Log( - LogLevel.Debug, - EventIds.HealthCheckData, - new HealthCheckDataLogValue(registration.Name, entry.Data), - null, - (state, ex) => state.ToString()); + if (entry.Data.Count > 0 && logger.IsEnabled(LogLevel.Debug)) + { + logger.Log( + LogLevel.Debug, + EventIds.HealthCheckData, + new HealthCheckDataLogValue(registration.Name, entry.Data), + null, + (state, ex) => state.ToString()); + } } } diff --git a/src/HealthChecks/HealthChecks/src/HealthCheckPublisherHostedService.cs b/src/HealthChecks/HealthChecks/src/HealthCheckPublisherHostedService.cs index 5167c80b3c37..834015dda495 100644 --- a/src/HealthChecks/HealthChecks/src/HealthCheckPublisherHostedService.cs +++ b/src/HealthChecks/HealthChecks/src/HealthCheckPublisherHostedService.cs @@ -20,7 +20,7 @@ internal sealed partial class HealthCheckPublisherHostedService : IHostedService private readonly ILogger _logger; private readonly IHealthCheckPublisher[] _publishers; - private CancellationTokenSource _stopping; + private readonly CancellationTokenSource _stopping; private Timer? _timer; private CancellationTokenSource? _runTokenSource; @@ -115,7 +115,7 @@ internal void CancelToken() internal async Task RunAsync() { var duration = ValueStopwatch.StartNew(); - HealthCheckPublisherProcessingBegin(); + Logger.HealthCheckPublisherProcessingBegin(_logger); CancellationTokenSource? cancellation = null; try @@ -128,7 +128,7 @@ internal async Task RunAsync() await RunAsyncCore(cancellation.Token); - HealthCheckPublisherProcessingEnd(duration.GetElapsedTime()); + Logger.HealthCheckPublisherProcessingEnd(_logger, duration.GetElapsedTime()); } catch (OperationCanceledException) when (IsStopping) { @@ -138,7 +138,7 @@ internal async Task RunAsync() catch (Exception ex) { // This is an error, publishing failed. - HealthCheckPublisherProcessingEnd(duration.GetElapsedTime(), ex); + Logger.HealthCheckPublisherProcessingEnd(_logger, duration.GetElapsedTime(), ex); } finally { @@ -170,10 +170,10 @@ private async Task RunPublisherAsync(IHealthCheckPublisher publisher, HealthRepo try { - HealthCheckPublisherBegin(publisher); + Logger.HealthCheckPublisherBegin(_logger, publisher); await publisher.PublishAsync(report, cancellationToken); - HealthCheckPublisherEnd(publisher, duration.GetElapsedTime()); + Logger.HealthCheckPublisherEnd(_logger, publisher, duration.GetElapsedTime()); } catch (OperationCanceledException) when (IsStopping) { @@ -182,12 +182,12 @@ private async Task RunPublisherAsync(IHealthCheckPublisher publisher, HealthRepo } catch (OperationCanceledException) { - HealthCheckPublisherTimeout(publisher, duration.GetElapsedTime()); + Logger.HealthCheckPublisherTimeout(_logger, publisher, duration.GetElapsedTime()); throw; } catch (Exception ex) { - HealthCheckPublisherError(publisher, duration.GetElapsedTime(), ex); + Logger.HealthCheckPublisherError(_logger, publisher, duration.GetElapsedTime(), ex); throw; } } @@ -201,44 +201,55 @@ internal static class EventIds public const int HealthCheckPublisherErrorId = 104; public const int HealthCheckPublisherTimeoutId = 104; - public static readonly EventId HealthCheckPublisherProcessingBegin = new EventId(HealthCheckPublisherProcessingBeginId, nameof(HealthCheckPublisherProcessingBegin)); - public static readonly EventId HealthCheckPublisherProcessingEnd = new EventId(HealthCheckPublisherProcessingEndId, nameof(HealthCheckPublisherProcessingEnd)); - public static readonly EventId HealthCheckPublisherBegin = new EventId(HealthCheckPublisherBeginId, nameof(HealthCheckPublisherBegin)); - public static readonly EventId HealthCheckPublisherEnd = new EventId(HealthCheckPublisherEndId, nameof(HealthCheckPublisherEnd)); - public static readonly EventId HealthCheckPublisherError = new EventId(HealthCheckPublisherErrorId, nameof(HealthCheckPublisherError)); - public static readonly EventId HealthCheckPublisherTimeout = new EventId(HealthCheckPublisherTimeoutId, nameof(HealthCheckPublisherTimeout)); + // Hard code the event names to avoid breaking changes. Even if the methods are renamed, these hard-coded names shouldn't change. + public const string HealthCheckPublisherProcessingBeginName = "HealthCheckPublisherProcessingBegin"; + public const string HealthCheckPublisherProcessingEndName = "HealthCheckPublisherProcessingEnd"; + public const string HealthCheckPublisherBeginName = "HealthCheckPublisherBegin"; + public const string HealthCheckPublisherEndName = "HealthCheckPublisherEnd"; + public const string HealthCheckPublisherErrorName = "HealthCheckPublisherError"; + public const string HealthCheckPublisherTimeoutName = "HealthCheckPublisherTimeout"; + + public static readonly EventId HealthCheckPublisherProcessingBegin = new EventId(HealthCheckPublisherProcessingBeginId, HealthCheckPublisherProcessingBeginName); + public static readonly EventId HealthCheckPublisherProcessingEnd = new EventId(HealthCheckPublisherProcessingEndId, HealthCheckPublisherProcessingEndName); + public static readonly EventId HealthCheckPublisherBegin = new EventId(HealthCheckPublisherBeginId, HealthCheckPublisherBeginName); + public static readonly EventId HealthCheckPublisherEnd = new EventId(HealthCheckPublisherEndId, HealthCheckPublisherEndName); + public static readonly EventId HealthCheckPublisherError = new EventId(HealthCheckPublisherErrorId, HealthCheckPublisherErrorName); + public static readonly EventId HealthCheckPublisherTimeout = new EventId(HealthCheckPublisherTimeoutId, HealthCheckPublisherTimeoutName); } - [LoggerMessage(EventId = EventIds.HealthCheckPublisherProcessingBeginId, Level = LogLevel.Debug, Message = "Running health check publishers")] - private partial void HealthCheckPublisherProcessingBegin(); + private static partial class Logger + { + [LoggerMessage(EventIds.HealthCheckPublisherProcessingBeginId, LogLevel.Debug, "Running health check publishers", EventName = EventIds.HealthCheckPublisherProcessingBeginName)] + public static partial void HealthCheckPublisherProcessingBegin(ILogger logger); - private void HealthCheckPublisherProcessingEnd(TimeSpan duration, Exception? exception = null) => - HealthCheckPublisherProcessingEnd(duration.TotalMilliseconds, exception); + public static void HealthCheckPublisherProcessingEnd(ILogger logger, TimeSpan duration, Exception? exception = null) => + HealthCheckPublisherProcessingEnd(logger, duration.TotalMilliseconds, exception); - [LoggerMessage(EventId = EventIds.HealthCheckPublisherProcessingEndId, Level = LogLevel.Debug, Message = "Health check publisher processing completed after {ElapsedMilliseconds}ms")] - private partial void HealthCheckPublisherProcessingEnd(double ElapsedMilliseconds, Exception? exception = null); + [LoggerMessage(EventIds.HealthCheckPublisherProcessingEndId, LogLevel.Debug, "Health check publisher processing completed after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckPublisherProcessingEndName)] + private static partial void HealthCheckPublisherProcessingEnd(ILogger logger, double ElapsedMilliseconds, Exception? exception = null); - [LoggerMessage(EventId = EventIds.HealthCheckPublisherBeginId, Level = LogLevel.Debug, Message = "Running health check publisher '{HealthCheckPublisher}'")] - private partial void HealthCheckPublisherBegin(IHealthCheckPublisher HealthCheckPublisher); + [LoggerMessage(EventIds.HealthCheckPublisherBeginId, LogLevel.Debug, "Running health check publisher '{HealthCheckPublisher}'", EventName = EventIds.HealthCheckPublisherBeginName)] + public static partial void HealthCheckPublisherBegin(ILogger logger, IHealthCheckPublisher HealthCheckPublisher); - private void HealthCheckPublisherEnd(IHealthCheckPublisher HealthCheckPublisher, TimeSpan duration) => - HealthCheckPublisherEnd(HealthCheckPublisher, duration.TotalMilliseconds); + public static void HealthCheckPublisherEnd(ILogger logger, IHealthCheckPublisher HealthCheckPublisher, TimeSpan duration) => + HealthCheckPublisherEnd(logger, HealthCheckPublisher, duration.TotalMilliseconds); - [LoggerMessage(EventId = EventIds.HealthCheckPublisherEndId, Level = LogLevel.Debug, Message = "Health check '{HealthCheckPublisher}' completed after {ElapsedMilliseconds}ms")] - private partial void HealthCheckPublisherEnd(IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds); + [LoggerMessage(EventIds.HealthCheckPublisherEndId, LogLevel.Debug, "Health check '{HealthCheckPublisher}' completed after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckPublisherEndName)] + private static partial void HealthCheckPublisherEnd(ILogger logger, IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds); - private void HealthCheckPublisherError(IHealthCheckPublisher publisher, TimeSpan duration, Exception exception) => - HealthCheckPublisherError(publisher, duration.TotalMilliseconds, exception); + public static void HealthCheckPublisherError(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration, Exception exception) => + HealthCheckPublisherError(logger, publisher, duration.TotalMilliseconds, exception); #pragma warning disable SYSLIB1006 - [LoggerMessage(EventId = EventIds.HealthCheckPublisherErrorId, Level = LogLevel.Error, Message = "Health check {HealthCheckPublisher} threw an unhandled exception after {ElapsedMilliseconds}ms")] - private partial void HealthCheckPublisherError(IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds, Exception exception); + [LoggerMessage(EventIds.HealthCheckPublisherErrorId, LogLevel.Error, "Health check {HealthCheckPublisher} threw an unhandled exception after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckPublisherErrorName)] + private static partial void HealthCheckPublisherError(ILogger logger, IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds, Exception exception); - private void HealthCheckPublisherTimeout(IHealthCheckPublisher publisher, TimeSpan duration) => - HealthCheckPublisherTimeout(publisher, duration.TotalMilliseconds); + public static void HealthCheckPublisherTimeout(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration) => + HealthCheckPublisherTimeout(logger, publisher, duration.TotalMilliseconds); - [LoggerMessage(EventId = EventIds.HealthCheckPublisherTimeoutId, Level = LogLevel.Error, Message = "Health check {HealthCheckPublisher} was canceled after {ElapsedMilliseconds}ms")] - private partial void HealthCheckPublisherTimeout(IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds); + [LoggerMessage(EventIds.HealthCheckPublisherTimeoutId, LogLevel.Error, "Health check {HealthCheckPublisher} was canceled after {ElapsedMilliseconds}ms", EventName = EventIds.HealthCheckPublisherTimeoutName)] + private static partial void HealthCheckPublisherTimeout(ILogger logger, IHealthCheckPublisher HealthCheckPublisher, double ElapsedMilliseconds); #pragma warning restore SYSLIB1006 + } } }