Browse Source

Add source-generated logging methods

pull/1318/head
copilot-swe-agent[bot] 5 months ago
committed by GitHub
parent
commit
19cff623e5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 27
      backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs
  2. 28
      backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs
  3. 7
      backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs
  4. 22
      backend/src/Squidex.Infrastructure/Migrations/Migrator.cs
  5. 7
      backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs

27
backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs

@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging;
namespace Squidex.Infrastructure.Commands; namespace Squidex.Infrastructure.Commands;
public sealed class LogCommandMiddleware(ILogger<LogCommandMiddleware> log) : ICommandMiddleware public sealed partial class LogCommandMiddleware(ILogger<LogCommandMiddleware> log) : ICommandMiddleware
{ {
public async Task HandleAsync(CommandContext context, NextDelegate next, public async Task HandleAsync(CommandContext context, NextDelegate next,
CancellationToken ct) CancellationToken ct)
@ -20,7 +20,7 @@ public sealed class LogCommandMiddleware(ILogger<LogCommandMiddleware> log) : IC
{ {
if (log.IsEnabled(LogLevel.Debug)) if (log.IsEnabled(LogLevel.Debug))
{ {
log.LogDebug("Command {command} with ID {id} started.", type, context.ContextId); LogCommandStarted(log, type, context.ContextId);
} }
var watch = ValueStopwatch.StartNew(); var watch = ValueStopwatch.StartNew();
@ -28,22 +28,37 @@ public sealed class LogCommandMiddleware(ILogger<LogCommandMiddleware> log) : IC
{ {
await next(context, ct); await next(context, ct);
log.LogInformation("Command {command} with ID {id} succeeded.", type, context.ContextId); LogCommandSucceeded(log, type, context.ContextId);
} }
finally finally
{ {
log.LogInformation("Command {command} with ID {id} completed after {time}ms.", type, context.ContextId, watch.Stop()); LogCommandCompleted(log, type, context.ContextId, watch.Stop());
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
log.LogError(ex, "Command {command} with ID {id} failed.", type, context.ContextId); LogCommandFailed(log, type, context.ContextId, ex);
throw; throw;
} }
if (!context.IsCompleted) if (!context.IsCompleted)
{ {
log.LogCritical("Command {command} with ID {id} not handled.", type, context.ContextId); LogCommandNotHandled(log, type, context.ContextId);
} }
} }
[LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "Command {command} with ID {id} started.")]
private static partial void LogCommandStarted(ILogger logger, Type command, Guid id);
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Command {command} with ID {id} succeeded.")]
private static partial void LogCommandSucceeded(ILogger logger, Type command, Guid id);
[LoggerMessage(EventId = 3, Level = LogLevel.Information, Message = "Command {command} with ID {id} completed after {time}ms.")]
private static partial void LogCommandCompleted(ILogger logger, Type command, Guid id, long time);
[LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Command {command} with ID {id} failed.")]
private static partial void LogCommandFailed(ILogger logger, Type command, Guid id, Exception exception);
[LoggerMessage(EventId = 5, Level = LogLevel.Critical, Message = "Command {command} with ID {id} not handled.")]
private static partial void LogCommandNotHandled(ILogger logger, Type command, Guid id);
} }

28
backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs

@ -13,7 +13,7 @@ using Squidex.Infrastructure.Tasks;
namespace Squidex.Infrastructure.EventSourcing.Consume; namespace Squidex.Infrastructure.EventSourcing.Consume;
public class EventConsumerProcessor : IEventSubscriber<ParsedEvents> public partial class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
{ {
private readonly SimpleState<EventConsumerState> state; private readonly SimpleState<EventConsumerState> state;
private readonly IEventFormatter eventFormatter; private readonly IEventFormatter eventFormatter;
@ -69,7 +69,7 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
} }
catch (Exception ex) catch (Exception ex)
{ {
log.LogCritical(ex, "Failed to complete consumer."); LogFailedToCompleteConsumer(log, ex);
} }
} }
@ -107,7 +107,7 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
if (logWindow.CanRetryAfterFailure()) if (logWindow.CanRetryAfterFailure())
{ {
log.LogError(exception, "Failed to handle event."); LogFailedToHandleEvent(log, exception);
} }
}, State.Position); }, State.Position);
} }
@ -215,8 +215,7 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
ex = new AggregateException(ex, unsubscribeException); ex = new AggregateException(ex, unsubscribeException);
} }
log.LogCritical(ex, "Failed to update consumer {consumer} at position {position} from {caller}.", LogFailedToUpdateConsumer(log, eventConsumer.Name, position, caller, ex);
eventConsumer.Name, position, caller);
State = previousState.Stopped(ex); State = previousState.Stopped(ex);
} }
@ -233,7 +232,7 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
{ {
if (log.IsEnabled(LogLevel.Debug)) if (log.IsEnabled(LogLevel.Debug))
{ {
log.LogDebug("Event consumer {consumer} reset started", eventConsumer.Name); LogEventConsumerResetStarted(log, eventConsumer.Name);
} }
var watch = ValueStopwatch.StartNew(); var watch = ValueStopwatch.StartNew();
@ -243,7 +242,7 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
} }
finally finally
{ {
log.LogDebug("Event consumer {consumer} reset completed after {time}ms.", eventConsumer.Name, watch.Stop()); LogEventConsumerResetCompleted(log, eventConsumer.Name, watch.Stop());
} }
} }
@ -282,4 +281,19 @@ public class EventConsumerProcessor : IEventSubscriber<ParsedEvents>
{ {
return eventStore.CreateSubscription(subscriber, eventConsumer.EventsFilter, State.Position); return eventStore.CreateSubscription(subscriber, eventConsumer.EventsFilter, State.Position);
} }
[LoggerMessage(EventId = 1, Level = LogLevel.Critical, Message = "Failed to complete consumer.")]
private static partial void LogFailedToCompleteConsumer(ILogger logger, Exception exception);
[LoggerMessage(EventId = 2, Level = LogLevel.Error, Message = "Failed to handle event.")]
private static partial void LogFailedToHandleEvent(ILogger logger, Exception exception);
[LoggerMessage(EventId = 3, Level = LogLevel.Critical, Message = "Failed to update consumer {consumer} at position {position} from {caller}.")]
private static partial void LogFailedToUpdateConsumer(ILogger logger, string consumer, string? position, string? caller, Exception exception);
[LoggerMessage(EventId = 4, Level = LogLevel.Debug, Message = "Event consumer {consumer} reset started")]
private static partial void LogEventConsumerResetStarted(ILogger logger, string consumer);
[LoggerMessage(EventId = 5, Level = LogLevel.Debug, Message = "Event consumer {consumer} reset completed after {time}ms.")]
private static partial void LogEventConsumerResetCompleted(ILogger logger, string consumer, long time);
} }

7
backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs

@ -13,7 +13,7 @@ using Squidex.Infrastructure.Timers;
namespace Squidex.Infrastructure.Log; namespace Squidex.Infrastructure.Log;
public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLogStore public sealed partial class BackgroundRequestLogStore : DisposableObjectBase, IRequestLogStore
{ {
private readonly IRequestLogRepository logRepository; private readonly IRequestLogRepository logRepository;
private readonly ILogger<BackgroundRequestLogStore> log; private readonly ILogger<BackgroundRequestLogStore> log;
@ -88,7 +88,7 @@ public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLo
} }
catch (Exception ex) catch (Exception ex)
{ {
log.LogError(ex, "Failed to track usage in background."); LogTrackUsageFailed(log, ex);
} }
finally finally
{ {
@ -127,4 +127,7 @@ public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLo
return Task.CompletedTask; return Task.CompletedTask;
} }
[LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "Failed to track usage in background.")]
private static partial void LogTrackUsageFailed(ILogger logger, Exception exception);
} }

22
backend/src/Squidex.Infrastructure/Migrations/Migrator.cs

@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging;
namespace Squidex.Infrastructure.Migrations; namespace Squidex.Infrastructure.Migrations;
public sealed class Migrator( public sealed partial class Migrator(
IMigrationStatus migrationStatus, IMigrationStatus migrationStatus,
IMigrationPath migrationPath, IMigrationPath migrationPath,
ILogger<Migrator> log) ILogger<Migrator> log)
@ -41,7 +41,7 @@ public sealed class Migrator(
{ {
var name = migration.ToString()!; var name = migration.ToString()!;
log.LogInformation("Migration {migration} started.", name); LogMigrationStarted(log, name);
try try
{ {
@ -49,11 +49,11 @@ public sealed class Migrator(
await migration.UpdateAsync(ct); await migration.UpdateAsync(ct);
log.LogInformation("Migration {migration} completed after {time}ms.", name, watch.Stop()); LogMigrationCompleted(log, name, watch.Stop());
} }
catch (Exception ex) catch (Exception ex)
{ {
log.LogCritical(ex, "Migration {migration} failed.", name); LogMigrationFailed(log, name, ex);
throw new MigrationFailedException(name, ex); throw new MigrationFailedException(name, ex);
} }
} }
@ -76,7 +76,7 @@ public sealed class Migrator(
{ {
while (!await migrationStatus.TryLockAsync(ct)) while (!await migrationStatus.TryLockAsync(ct))
{ {
log.LogInformation("Could not acquire lock to start migrating. Trying again in {time}ms.", LockWaitMs); LogMigrationLockRetry(log, LockWaitMs);
await Task.Delay(LockWaitMs, ct); await Task.Delay(LockWaitMs, ct);
} }
} }
@ -92,4 +92,16 @@ public sealed class Migrator(
{ {
return migrationStatus.UnlockAsync(); return migrationStatus.UnlockAsync();
} }
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Migration {migration} started.")]
private static partial void LogMigrationStarted(ILogger logger, string migration);
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Migration {migration} completed after {time}ms.")]
private static partial void LogMigrationCompleted(ILogger logger, string migration, long time);
[LoggerMessage(EventId = 3, Level = LogLevel.Critical, Message = "Migration {migration} failed.")]
private static partial void LogMigrationFailed(ILogger logger, string migration, Exception exception);
[LoggerMessage(EventId = 4, Level = LogLevel.Information, Message = "Could not acquire lock to start migrating. Trying again in {time}ms.")]
private static partial void LogMigrationLockRetry(ILogger logger, int time);
} }

7
backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs

@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
namespace Squidex.Web.Pipeline; namespace Squidex.Web.Pipeline;
public sealed class RequestExceptionMiddleware(RequestDelegate next) public sealed partial class RequestExceptionMiddleware(RequestDelegate next)
{ {
private static readonly ActionDescriptor EmptyActionDescriptor = new ActionDescriptor(); private static readonly ActionDescriptor EmptyActionDescriptor = new ActionDescriptor();
private static readonly RouteData EmptyRouteData = new RouteData(); private static readonly RouteData EmptyRouteData = new RouteData();
@ -37,7 +37,7 @@ public sealed class RequestExceptionMiddleware(RequestDelegate next)
} }
catch (Exception ex) catch (Exception ex)
{ {
log.LogError(ex, "An unexpected exception has occurred."); LogUnexpectedException(log, ex);
if (!context.Response.HasStarted) if (!context.Response.HasStarted)
{ {
@ -77,4 +77,7 @@ public sealed class RequestExceptionMiddleware(RequestDelegate next)
{ {
return statusCode is >= 400 and < 600; return statusCode is >= 400 and < 600;
} }
[LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "An unexpected exception has occurred.")]
private static partial void LogUnexpectedException(ILogger logger, Exception exception);
} }

Loading…
Cancel
Save