Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert HealthChecks logging to use new Logging Source Generator #32414

Merged
merged 3 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 44 additions & 61 deletions src/HealthChecks/HealthChecks/src/DefaultHealthCheckService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
internal class DefaultHealthCheckService : HealthCheckService
internal partial class DefaultHealthCheckService : HealthCheckService
pranavkm marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IOptions<HealthCheckServiceOptions> _options;
Expand Down Expand Up @@ -87,7 +87,7 @@ private async Task<HealthReportEntry> RunCheckAsync(HealthCheckRegistration regi
var stopwatch = ValueStopwatch.StartNew();
var context = new HealthCheckContext { Registration = registration };

Log.HealthCheckBegin(_logger, registration);
Log.HealthCheckBegin(_logger, registration.Name);

HealthReportEntry entry;
CancellationTokenSource? timeoutCancellationTokenSource = null;
Expand Down Expand Up @@ -182,92 +182,75 @@ private static void ValidateRegistrations(IEnumerable<HealthCheckRegistration> r

internal static class EventIds
{
public static readonly EventId HealthCheckProcessingBegin = new EventId(100, "HealthCheckProcessingBegin");
public static readonly EventId HealthCheckProcessingEnd = new EventId(101, "HealthCheckProcessingEnd");

public static readonly EventId HealthCheckBegin = new EventId(102, "HealthCheckBegin");
public static readonly EventId HealthCheckEnd = new EventId(103, "HealthCheckEnd");
public static readonly EventId HealthCheckError = new EventId(104, "HealthCheckError");
public static readonly EventId HealthCheckData = new EventId(105, "HealthCheckData");
public const int HealthCheckProcessingBeginId = 100;
public const int HealthCheckProcessingEndId = 101;
public const int HealthCheckBeginId = 102;
public const int HealthCheckEndId = 103;
public const int HealthCheckErrorId = 104;
public const int HealthCheckDataId = 105;

// 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 HealthCheckData = new EventId(HealthCheckDataId, HealthCheckDataName);
}

private static class Log
private static partial class Log
{
private static readonly Action<ILogger, Exception?> _healthCheckProcessingBegin = LoggerMessage.Define(
LogLevel.Debug,
EventIds.HealthCheckProcessingBegin,
"Running health checks");
[LoggerMessage(EventIds.HealthCheckProcessingBeginId, LogLevel.Debug, "Running health checks", EventName = EventIds.HealthCheckProcessingBeginName)]
public static partial void HealthCheckProcessingBegin(ILogger logger);

public static void HealthCheckProcessingEnd(ILogger logger, HealthStatus status, TimeSpan duration) =>
HealthCheckProcessingEnd(logger, status, duration.TotalMilliseconds);

private static readonly Action<ILogger, double, HealthStatus, Exception?> _healthCheckProcessingEnd = LoggerMessage.Define<double, HealthStatus>(
LogLevel.Debug,
EventIds.HealthCheckProcessingEnd,
"Health check processing with combined status {HealthStatus} completed after {ElapsedMilliseconds}ms");
[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);

private static readonly Action<ILogger, string, Exception?> _healthCheckBegin = LoggerMessage.Define<string>(
LogLevel.Debug,
EventIds.HealthCheckBegin,
"Running health check {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}'";

private static readonly Action<ILogger, string, double, HealthStatus, string?, Exception?> _healthCheckEndHealthy = LoggerMessage.Define<string, double, HealthStatus, string?>(
LogLevel.Debug,
EventIds.HealthCheckEnd,
HealthCheckEndText);

private static readonly Action<ILogger, string, double, HealthStatus, string?, Exception?> _healthCheckEndDegraded = LoggerMessage.Define<string, double, HealthStatus, string?>(
LogLevel.Warning,
EventIds.HealthCheckEnd,
HealthCheckEndText);

private static readonly Action<ILogger, string, double, HealthStatus, string?, Exception?> _healthCheckEndUnhealthy = LoggerMessage.Define<string, double, HealthStatus, string?>(
LogLevel.Error,
EventIds.HealthCheckEnd,
HealthCheckEndText);
#pragma warning disable SYSLIB1006
[LoggerMessage(EventIds.HealthCheckEndId, LogLevel.Debug, HealthCheckEndText, EventName = EventIds.HealthCheckEndName)]
private static partial void HealthCheckEndHealthy(ILogger logger, string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription);

private static readonly Action<ILogger, string, double, Exception?> _healthCheckError = LoggerMessage.Define<string, double>(
LogLevel.Error,
EventIds.HealthCheckError,
"Health check {HealthCheckName} threw an unhandled exception after {ElapsedMilliseconds}ms");
[LoggerMessage(EventIds.HealthCheckEndId, LogLevel.Warning, HealthCheckEndText, EventName = EventIds.HealthCheckEndName)]
private static partial void HealthCheckEndDegraded(ILogger logger, string HealthCheckName, HealthStatus HealthStatus, double ElapsedMilliseconds, string? HealthCheckDescription);

public static void HealthCheckProcessingBegin(ILogger logger)
{
_healthCheckProcessingBegin(logger, null);
}

public static void HealthCheckProcessingEnd(ILogger logger, HealthStatus status, TimeSpan duration)
{
_healthCheckProcessingEnd(logger, duration.TotalMilliseconds, status, null);
}

public static void HealthCheckBegin(ILogger logger, HealthCheckRegistration registration)
{
_healthCheckBegin(logger, registration.Name, null);
}
[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

public static void HealthCheckEnd(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration)
{
switch (entry.Status)
{
case HealthStatus.Healthy:
_healthCheckEndHealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
HealthCheckEndHealthy(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description);
break;

case HealthStatus.Degraded:
_healthCheckEndDegraded(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
HealthCheckEndDegraded(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description);
break;

case HealthStatus.Unhealthy:
_healthCheckEndUnhealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, entry.Exception);
HealthCheckEndUnhealthy(logger, registration.Name, entry.Status, duration.TotalMilliseconds, entry.Description, entry.Exception);
break;
}
}

public static void HealthCheckError(ILogger logger, HealthCheckRegistration registration, Exception exception, TimeSpan duration)
{
_healthCheckError(logger, registration.Name, duration.TotalMilliseconds, 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);

public static void HealthCheckError(ILogger logger, HealthCheckRegistration registration, Exception exception, TimeSpan duration) =>
HealthCheckError(logger, registration.Name, duration.TotalMilliseconds, exception);

public static void HealthCheckData(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry)
{
Expand Down
108 changes: 43 additions & 65 deletions src/HealthChecks/HealthChecks/src/HealthCheckPublisherHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@

namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
internal sealed class HealthCheckPublisherHostedService : IHostedService
internal sealed partial class HealthCheckPublisherHostedService : IHostedService
{
private readonly HealthCheckService _healthCheckService;
private readonly IOptions<HealthCheckPublisherOptions> _options;
private readonly ILogger _logger;
private readonly IHealthCheckPublisher[] _publishers;

private CancellationTokenSource _stopping;
private readonly CancellationTokenSource _stopping;
private Timer? _timer;
private CancellationTokenSource? _runTokenSource;

Expand Down Expand Up @@ -194,77 +194,55 @@ private async Task RunPublisherAsync(IHealthCheckPublisher publisher, HealthRepo

internal static class EventIds
{
public static readonly EventId HealthCheckPublisherProcessingBegin = new EventId(100, "HealthCheckPublisherProcessingBegin");
public static readonly EventId HealthCheckPublisherProcessingEnd = new EventId(101, "HealthCheckPublisherProcessingEnd");
public static readonly EventId HealthCheckPublisherProcessingError = new EventId(101, "HealthCheckPublisherProcessingError");

public static readonly EventId HealthCheckPublisherBegin = new EventId(102, "HealthCheckPublisherBegin");
public static readonly EventId HealthCheckPublisherEnd = new EventId(103, "HealthCheckPublisherEnd");
public static readonly EventId HealthCheckPublisherError = new EventId(104, "HealthCheckPublisherError");
public static readonly EventId HealthCheckPublisherTimeout = new EventId(104, "HealthCheckPublisherTimeout");
public const int HealthCheckPublisherProcessingBeginId = 100;
public const int HealthCheckPublisherProcessingEndId = 101;
public const int HealthCheckPublisherBeginId = 102;
public const int HealthCheckPublisherEndId = 103;
public const int HealthCheckPublisherErrorId = 104;
public const int HealthCheckPublisherTimeoutId = 104;

// 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";
}

private static class Logger
private static partial class Logger
{
private static readonly Action<ILogger, Exception?> _healthCheckPublisherProcessingBegin = LoggerMessage.Define(
LogLevel.Debug,
EventIds.HealthCheckPublisherProcessingBegin,
"Running health check publishers");

private static readonly Action<ILogger, double, Exception?> _healthCheckPublisherProcessingEnd = LoggerMessage.Define<double>(
LogLevel.Debug,
EventIds.HealthCheckPublisherProcessingEnd,
"Health check publisher processing completed after {ElapsedMilliseconds}ms");

private static readonly Action<ILogger, IHealthCheckPublisher, Exception?> _healthCheckPublisherBegin = LoggerMessage.Define<IHealthCheckPublisher>(
LogLevel.Debug,
EventIds.HealthCheckPublisherBegin,
"Running health check publisher '{HealthCheckPublisher}'");

private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception?> _healthCheckPublisherEnd = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Debug,
EventIds.HealthCheckPublisherEnd,
"Health check '{HealthCheckPublisher}' completed after {ElapsedMilliseconds}ms");

private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception?> _healthCheckPublisherError = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Error,
EventIds.HealthCheckPublisherError,
"Health check {HealthCheckPublisher} threw an unhandled exception after {ElapsedMilliseconds}ms");

private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception?> _healthCheckPublisherTimeout = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Error,
EventIds.HealthCheckPublisherTimeout,
"Health check {HealthCheckPublisher} was canceled after {ElapsedMilliseconds}ms");

public static void HealthCheckPublisherProcessingBegin(ILogger logger)
{
_healthCheckPublisherProcessingBegin(logger, null);
}
[LoggerMessage(EventIds.HealthCheckPublisherProcessingBeginId, LogLevel.Debug, "Running health check publishers", EventName = EventIds.HealthCheckPublisherProcessingBeginName)]
public static partial void HealthCheckPublisherProcessingBegin(ILogger logger);

public static void HealthCheckPublisherProcessingEnd(ILogger logger, TimeSpan duration, Exception? exception = null)
{
_healthCheckPublisherProcessingEnd(logger, duration.TotalMilliseconds, exception);
}
public static void HealthCheckPublisherProcessingEnd(ILogger logger, TimeSpan duration, Exception? exception = null) =>
HealthCheckPublisherProcessingEnd(logger, duration.TotalMilliseconds, exception);

public static void HealthCheckPublisherBegin(ILogger logger, IHealthCheckPublisher publisher)
{
_healthCheckPublisherBegin(logger, publisher, 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);

public static void HealthCheckPublisherEnd(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration)
{
_healthCheckPublisherEnd(logger, publisher, duration.TotalMilliseconds, null);
}
[LoggerMessage(EventIds.HealthCheckPublisherBeginId, LogLevel.Debug, "Running health check publisher '{HealthCheckPublisher}'", EventName = EventIds.HealthCheckPublisherBeginName)]
public static partial void HealthCheckPublisherBegin(ILogger logger, IHealthCheckPublisher HealthCheckPublisher);

public static void HealthCheckPublisherError(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration, Exception exception)
{
_healthCheckPublisherError(logger, publisher, duration.TotalMilliseconds, exception);
}
public static void HealthCheckPublisherEnd(ILogger logger, IHealthCheckPublisher HealthCheckPublisher, TimeSpan duration) =>
HealthCheckPublisherEnd(logger, HealthCheckPublisher, duration.TotalMilliseconds);

public static void HealthCheckPublisherTimeout(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration)
{
_healthCheckPublisherTimeout(logger, publisher, duration.TotalMilliseconds, null);
}
[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);

public static void HealthCheckPublisherError(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration, Exception exception) =>
HealthCheckPublisherError(logger, publisher, duration.TotalMilliseconds, exception);

#pragma warning disable SYSLIB1006
[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);

public static void HealthCheckPublisherTimeout(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration) =>
HealthCheckPublisherTimeout(logger, publisher, duration.TotalMilliseconds);

[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
}
}
}
Loading