diff --git a/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs b/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs index db06c90a97..5b5210c728 100644 --- a/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs +++ b/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs @@ -104,7 +104,7 @@ private static void LogMessage(ILogger log, LogMessage message) private static void LogError(ILogger log, Error error) { - log.LogWarning("Kafka error with {code} and {reason}.", error.Code, error.Reason); + LogMessages.LogKafkaError(log, error.Code, error.Reason); } public async Task SendAsync(KafkaMessageRequest job, diff --git a/backend/extensions/Squidex.Extensions/Assets/Azure/AzureMetadataSource.cs b/backend/extensions/Squidex.Extensions/Assets/Azure/AzureMetadataSource.cs index 91f0890689..08dca3ff2a 100644 --- a/backend/extensions/Squidex.Extensions/Assets/Azure/AzureMetadataSource.cs +++ b/backend/extensions/Squidex.Extensions/Assets/Azure/AzureMetadataSource.cs @@ -84,7 +84,7 @@ public async Task EnhanceAsync(UploadAssetCommand command, } catch (Exception ex) { - log.LogError(ex, "Failed to enrich asset."); + LogMessages.LogFailedToEnrichAsset(log, ex); } } diff --git a/backend/extensions/Squidex.Extensions/LogMessages.cs b/backend/extensions/Squidex.Extensions/LogMessages.cs new file mode 100644 index 0000000000..8d43ba40e7 --- /dev/null +++ b/backend/extensions/Squidex.Extensions/LogMessages.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex.Extensions; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Warning, Message = "Kafka error with {code} and {reason}.")] + public static partial void LogKafkaError(ILogger logger, object code, string reason); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to enrich asset.")] + public static partial void LogFailedToEnrichAsset(ILogger logger, Exception exception); +} diff --git a/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/LogMessages.cs b/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/LogMessages.cs new file mode 100644 index 0000000000..e5f79581d6 --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/LogMessages.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex.Infrastructure.Counts; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to update count for collection {collection}.")] + public static partial void LogFailedToUpdateCount(ILogger logger, string collection, Exception exception); +} diff --git a/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/MongoCountCollection.cs b/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/MongoCountCollection.cs index ff0ab65cae..a1e397799a 100644 --- a/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/MongoCountCollection.cs +++ b/backend/src/Squidex.Data.MongoDb/Infrastructure/Counts/MongoCountCollection.cs @@ -50,7 +50,7 @@ private async Task RefreshSilentAsync(string key, long cachedCount, Func CreateJobsAsync(Envelope @event, Rule CreateJobs(@event, context, states, ct) .Catch(ex => { - log.LogError(ex, "Failed to create rule job."); + LogMessages.LogFailedToCreateRuleJob(log, ex); return states.Select(state => JobResult.Skipped(state.Rule, SkipReason.Failed)); }); @@ -237,7 +237,7 @@ private async IAsyncEnumerable CreateJobs(Envelope @event, Ru CreateTriggerJobs(typed, triggerHandler, rulesByTrigger, context, ct) .Catch(ex => { - log.LogError(ex, "Failed to create rule jobs from trigger."); + LogMessages.LogFailedToCreateRuleJobsFromTrigger(log, ex); return states.Select(state => JobResult.Skipped(state.Rule, SkipReason.Failed)); }); @@ -263,7 +263,7 @@ private async IAsyncEnumerable CreateTriggerJobs(Envelope @ CreateEventJobs(@event, enrichedEvent, triggerHandler, states, context) .Catch(ex => { - log.LogError(ex, "Failed to create rule jobs from event."); + LogMessages.LogFailedToCreateRuleJobsFromEvent(log, ex); return states.Select(state => new JobResult diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/LogMessages.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/LogMessages.cs new file mode 100644 index 0000000000..fcd61d12ed --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/LogMessages.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex.Domain.Apps.Core; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to create rule job.")] + public static partial void LogFailedToCreateRuleJob(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to create rule jobs from trigger.")] + public static partial void LogFailedToCreateRuleJobsFromTrigger(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to create rule jobs from event.")] + public static partial void LogFailedToCreateRuleJobsFromEvent(ILogger logger, Exception exception); +} diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs index b4ac8dbc40..1d8962335c 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs @@ -58,7 +58,7 @@ async Task PublishAsync(SquidexCommand command) } catch (Exception ex) { - log.LogError(ex, "Failed to delete asset recursively."); + LogMessages.LogFailedToDeleteAssetRecursively(log, ex); } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreJob.cs b/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreJob.cs index fa8076159e..8df2100178 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreJob.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreJob.cs @@ -107,7 +107,7 @@ public async Task RunAsync(JobRunContext context, await context.LogAsync(" * Restore all objects like app, schemas and contents"); await context.LogAsync(" * Complete the restore operation for all objects"); await context.FlushAsync(); - log.LogInformation("Backup with job id {backupId} with from URL '{url}' started.", context.Job.Id, state.Url); + LogMessages.LogRestoreJobStarted(log, context.Job.Id, state.Url); state.Reader = await DownloadAsync(context, state, ct); @@ -147,7 +147,7 @@ public async Task RunAsync(JobRunContext context, await AssignContributorAsync(context, state); await context.LogAsync("Completed, Yeah!"); - log.LogInformation("Backup with job id {backupId} from URL '{url}' completed.", context.Job.Id, state.Url); + LogMessages.LogRestoreJobCompleted(log, context.Job.Id, state.Url); } catch (Exception ex) { @@ -168,7 +168,7 @@ public async Task RunAsync(JobRunContext context, await context.LogAsync(message); - log.LogError(ex, "Backup with job id {backupId} from URL '{url}' failed.", context.Job.Id, state.Url); + LogMessages.LogRestoreJobFailed(log, context.Job.Id, state.Url, ex); throw; } finally @@ -231,7 +231,7 @@ private async Task CleanupAsync(State state) } catch (Exception ex) { - log.LogError(ex, "Failed to clean up restore."); + LogMessages.LogFailedToCleanUpRestore(log, ex); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Collaboration/CommentCollaborationHandler.cs b/backend/src/Squidex.Domain.Apps.Entities/Collaboration/CommentCollaborationHandler.cs index 33005c0c31..8701f7a69a 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Collaboration/CommentCollaborationHandler.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Collaboration/CommentCollaborationHandler.cs @@ -116,7 +116,7 @@ public ValueTask OnDocumentLoadedAsync(DocumentLoadEvent @event) catch (Exception ex) { // We are in an extra task, so the exception would be probably swallowed. - log.LogError(ex, "Failed to handle yjs event."); + LogMessages.LogFailedToHandleYjsEvent(log, ex); throw; } }); diff --git a/backend/src/Squidex.Domain.Apps.Entities/Collaboration/EmailUserNotifications.cs b/backend/src/Squidex.Domain.Apps.Entities/Collaboration/EmailUserNotifications.cs index e36c232fbd..e480ca3de4 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Collaboration/EmailUserNotifications.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Collaboration/EmailUserNotifications.cs @@ -123,13 +123,13 @@ private async Task SendEmailAsync(string template, string emailSubj, string emai { if (string.IsNullOrWhiteSpace(emailBody)) { - log.LogWarning("Cannot send email to {email}: No email subject configured for template {template}.", template, user.Email); + LogMessages.LogNoEmailSubjectConfigured(log, template, user.Email); return; } if (string.IsNullOrWhiteSpace(emailSubj)) { - log.LogWarning("Cannot send email to {email}: No email body configured for template {template}.", template, user.Email); + LogMessages.LogNoEmailBodyConfigured(log, template, user.Email); return; } @@ -146,7 +146,7 @@ private async Task SendEmailAsync(string template, string emailSubj, string emai } catch (Exception ex) { - log.LogError(ex, "Failed to send notification to {email}.", user.Email); + LogMessages.LogFailedToSendNotification(log, user.Email, ex); throw; } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs index 56090ef556..6910b6e111 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs @@ -55,7 +55,7 @@ public async Task PublishAsync( } catch (Exception ex) { - log.LogError(ex, "Failed to query scheduled status changes-"); + LogMessages.LogFailedToQueryScheduledStatusChanges(log, ex); } } @@ -88,7 +88,7 @@ private async Task TryPublishAsync(Content content) } catch (Exception ex) { - log.LogError(ex, "Failed to execute scheduled status change for content '{contentId}'.", content.Id); + LogMessages.LogFailedToExecuteScheduledStatusChange(log, content.Id, ex); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ErrorVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ErrorVisitor.cs index f5c5c3f373..7bb372f0e8 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ErrorVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ErrorVisitor.cs @@ -26,11 +26,11 @@ public static void HandleError(this ExecutionOptions options, IServiceProvider s if (!string.IsNullOrWhiteSpace(fieldName)) { - log.LogError(context.OriginalException, "Failed to resolve field {field}.", fieldName); + LogMessages.LogFailedToResolveField(log, fieldName, context.OriginalException); } else { - log.LogError(context.OriginalException, "Failed to resolve execute query."); + LogMessages.LogFailedToResolveQuery(log, context.OriginalException); } if (context.OriginalException is ValidationException or DomainException) diff --git a/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs b/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs index 4a9943f323..e78149eb03 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs @@ -128,11 +128,11 @@ private async Task UpsertUserAsync(IUser user) } catch (NotifoException ex) { - log.LogError(ex, "Failed to register user in notifo: {details}.", ex.ToString()); + LogMessages.LogFailedToRegisterUserInNotifoWithDetails(log, ex.ToString(), ex); } catch (Exception ex) { - log.LogError(ex, "Failed to register user in notifo."); + LogMessages.LogFailedToRegisterUserInNotifo(log, ex); } } @@ -191,11 +191,11 @@ public async Task HandleEventsAsync(IEnumerable<(Envelope AppEvent, Hist } catch (NotifoException ex) { - log.LogError(ex, "Failed to push user to notifo: {details}.", ex.ToString()); + LogMessages.LogFailedToPushUserToNotifoWithDetails(log, ex.ToString(), ex); } catch (Exception ex) { - log.LogError(ex, "Failed to push user to notifo."); + LogMessages.LogFailedToPushUserToNotifo(log, ex); } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Invitation/InvitationEventConsumer.cs b/backend/src/Squidex.Domain.Apps.Entities/Invitation/InvitationEventConsumer.cs index 45854d0bbb..853c15372a 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Invitation/InvitationEventConsumer.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Invitation/InvitationEventConsumer.cs @@ -106,7 +106,7 @@ public async Task On(Envelope @event) if (assigner == null) { - log.LogWarning("Failed to invite user: Assigner {assignerId} not found.", assignerId); + LogMessages.LogInvitationAssignerNotFound(log, assignerId); return default; } @@ -114,7 +114,7 @@ public async Task On(Envelope @event) if (assignee == null) { - log.LogWarning("Failed to invite user: Assignee {assigneeId} not found.", assigneeId); + LogMessages.LogInvitationAssigneeNotFound(log, assigneeId); return default; } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs index 601371d3b9..073a13e682 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs @@ -59,7 +59,7 @@ public async Task LoadAsync( if (pending.Any()) { // This should actually never happen, so we log with warning. - log.LogWarning("Removed unfinished jobs for owner {ownerId} after start.", ownerId); + LogMessages.LogRemovedUnfinishedJobs(log, ownerId); foreach (var job in pending.ToList()) { @@ -81,7 +81,7 @@ public Task DeleteAsync(DomainId jobId) { return scheduler.ScheduleAsync(async _ => { - log.LogInformation("Clearing jobs for owner {ownerId}.", ownerId); + LogMessages.LogClearingJobs(log, ownerId); var job = state.Value.Jobs.Find(x => x.Id == jobId); @@ -105,7 +105,7 @@ public Task ClearAsync() { return scheduler.ScheduleAsync(async _ => { - log.LogInformation("Clearing jobs for owner {ownerId}.", ownerId); + LogMessages.LogClearingJobs(log, ownerId); foreach (var job in state.Value.Jobs) { @@ -164,7 +164,7 @@ public Task RunAsync(JobRequest request, OwnerId = ownerId, }; - log.LogInformation("Starting new backup with backup id '{backupId}' for owner {ownerId}.", context.Job.Id, ownerId); + LogMessages.LogStartingJob(log, context.Job.Id, ownerId); state.Value.Jobs.Insert(0, context.Job); try @@ -221,7 +221,7 @@ private async Task ProcessAsync(JobRunContext context, IJobRunner runner, } catch (Exception ex) { - log.LogError(ex, "Failed to run job with ID {jobId}.", context.Job.Id); + LogMessages.LogFailedToRunJob(log, context.Job.Id, ex); await SetStatusAsync(context, JobStatus.Failed); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/LogMessages.cs b/backend/src/Squidex.Domain.Apps.Entities/LogMessages.cs new file mode 100644 index 0000000000..44d7ed2a50 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Entities/LogMessages.cs @@ -0,0 +1,92 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; +using Squidex.Infrastructure; + +namespace Squidex.Domain.Apps.Entities; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to register user in notifo: {details}.")] + public static partial void LogFailedToRegisterUserInNotifoWithDetails(ILogger logger, string details, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to register user in notifo.")] + public static partial void LogFailedToRegisterUserInNotifo(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to push user to notifo: {details}.")] + public static partial void LogFailedToPushUserToNotifoWithDetails(ILogger logger, string details, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to push user to notifo.")] + public static partial void LogFailedToPushUserToNotifo(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to delete asset recursively.")] + public static partial void LogFailedToDeleteAssetRecursively(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Information, Message = "Backup with job id {backupId} with from URL '{url}' started.")] + public static partial void LogRestoreJobStarted(ILogger logger, DomainId backupId, Uri url); + + [LoggerMessage(Level = LogLevel.Information, Message = "Backup with job id {backupId} from URL '{url}' completed.")] + public static partial void LogRestoreJobCompleted(ILogger logger, DomainId backupId, Uri url); + + [LoggerMessage(Level = LogLevel.Error, Message = "Backup with job id {backupId} from URL '{url}' failed.")] + public static partial void LogRestoreJobFailed(ILogger logger, DomainId backupId, Uri url, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to clean up restore.")] + public static partial void LogFailedToCleanUpRestore(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to handle yjs event.")] + public static partial void LogFailedToHandleYjsEvent(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Cannot send email to {email}: No email subject configured for template {template}.")] + public static partial void LogNoEmailSubjectConfigured(ILogger logger, string email, string template); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Cannot send email to {email}: No email body configured for template {template}.")] + public static partial void LogNoEmailBodyConfigured(ILogger logger, string email, string template); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to send notification to {email}.")] + public static partial void LogFailedToSendNotification(ILogger logger, string email, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to query scheduled status changes-")] + public static partial void LogFailedToQueryScheduledStatusChanges(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to execute scheduled status change for content '{contentId}'.")] + public static partial void LogFailedToExecuteScheduledStatusChange(ILogger logger, DomainId contentId, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to resolve field {field}.")] + public static partial void LogFailedToResolveField(ILogger logger, string field, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to resolve execute query.")] + public static partial void LogFailedToResolveQuery(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Failed to invite user: Assigner {assignerId} not found.")] + public static partial void LogInvitationAssignerNotFound(ILogger logger, RefToken assignerId); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Failed to invite user: Assignee {assigneeId} not found.")] + public static partial void LogInvitationAssigneeNotFound(ILogger logger, string assigneeId); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Removed unfinished jobs for owner {ownerId} after start.")] + public static partial void LogRemovedUnfinishedJobs(ILogger logger, DomainId ownerId); + + [LoggerMessage(Level = LogLevel.Information, Message = "Clearing jobs for owner {ownerId}.")] + public static partial void LogClearingJobs(ILogger logger, DomainId ownerId); + + [LoggerMessage(Level = LogLevel.Information, Message = "Starting new backup with backup id '{backupId}' for owner {ownerId}.")] + public static partial void LogStartingJob(ILogger logger, DomainId backupId, DomainId ownerId); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to run job with ID {jobId}.")] + public static partial void LogFailedToRunJob(ILogger logger, DomainId jobId, Exception exception); + + [LoggerMessage(Level = LogLevel.Information, Message = "Adding rule job for Rule(trigger={ruleTrigger})")] + public static partial void LogAddingRuleJob(ILogger logger, string ruleTrigger); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Failed to run rule with ID {ruleId}, continue with next job.")] + public static partial void LogFailedToRunRule(ILogger logger, DomainId? ruleId, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to execute search from source {source} with query '{query}'.")] + public static partial void LogFailedToExecuteSearch(ILogger logger, string source, string query, Exception exception); +} diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/RuleQueueWriter.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/RuleQueueWriter.cs index a7b0b8e79f..4677de6447 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Rules/RuleQueueWriter.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Rules/RuleQueueWriter.cs @@ -35,8 +35,10 @@ result.SkipReason is not(SkipReason.None or SkipReason.Disabled)) writes.Add(result.Job.Value); - log?.LogInformation("Adding rule job for Rule(trigger={ruleTrigger})", - result.Rule.Trigger.GetType().Name); + if (log != null) + { + LogMessages.LogAddingRuleJob(log, result.Rule.Trigger.GetType().Name); + } var today = Clock.GetCurrentInstant().ToDateOnly(); diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/Runner/RuleRunnerJob.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/Runner/RuleRunnerJob.cs index a38943b71f..4628dba7e7 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Rules/Runner/RuleRunnerJob.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Rules/Runner/RuleRunnerJob.cs @@ -171,8 +171,7 @@ private async Task EnqueueFromSnapshotsAsync(RuleContext context, throw result.EnrichmentError; } - log.LogWarning(result.EnrichmentError, "Failed to run rule with ID {ruleId}, continue with next job.", - result.Rule?.Id); + LogMessages.LogFailedToRunRule(log, result.Rule?.Id, result.EnrichmentError); } } } @@ -212,8 +211,7 @@ private async Task EnqueueFromEventsAsync(JobRunContext run, RuleContext context throw result.EnrichmentError; } - log.LogWarning(result.EnrichmentError, "Failed to run rule with ID {ruleId}, continue with next job.", - result.Rule?.Id); + LogMessages.LogFailedToRunRule(log, result.Rule?.Id, result.EnrichmentError); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs b/backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs index fcde9e6f1a..9c6e03f27e 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs @@ -37,7 +37,7 @@ private async Task SearchAsync(ISearchSource source, string query } catch (Exception ex) { - log.LogError(ex, "Failed to execute search from source {source} with query '{query}'.", source, query); + LogMessages.LogFailedToExecuteSearch(log, source.GetType().Name, query, ex); return Empty; } } diff --git a/backend/src/Squidex.Domain.Users/DefaultUserService.cs b/backend/src/Squidex.Domain.Users/DefaultUserService.cs index 4717c1bcb2..6f97a77984 100644 --- a/backend/src/Squidex.Domain.Users/DefaultUserService.cs +++ b/backend/src/Squidex.Domain.Users/DefaultUserService.cs @@ -195,7 +195,7 @@ public async Task CreateAsync(string email, UserValues? values = null, bo } catch (Exception ex2) { - log.LogError(ex2, "Failed to cleanup user after creation failed."); + LogMessages.LogFailedToCleanupUser(log, ex2); } throw; diff --git a/backend/src/Squidex.Domain.Users/LogMessages.cs b/backend/src/Squidex.Domain.Users/LogMessages.cs new file mode 100644 index 0000000000..24d9682ae3 --- /dev/null +++ b/backend/src/Squidex.Domain.Users/LogMessages.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex.Domain.Users; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to cleanup user after creation failed.")] + public static partial void LogFailedToCleanupUser(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Identity operation failed: {errorMessage}.")] + public static partial void LogIdentityOperationFailed(ILogger logger, string errorMessage); +} diff --git a/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs b/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs index daceb64a83..4826b7f6cc 100644 --- a/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs +++ b/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs @@ -46,7 +46,7 @@ static string Localize(IdentityError error) var errorMessage = errorMessageBuilder.ToString(); - log.LogError("Identity operation failed: {errorMessage}.", errorMessage); + LogMessages.LogIdentityOperationFailed(log, errorMessage); throw new ValidationException(result.Errors.Select(x => new ValidationError(Localize(x))).ToList()); } diff --git a/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs b/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs index 07a1d31f28..afb2180315 100644 --- a/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs +++ b/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs @@ -152,7 +152,7 @@ public virtual async Task EnsureLoadedAsync( } catch (Exception ex) { - log.LogError(ex, "Failed to repair snapshot for domain object of type {type} with ID {id}.", GetType(), UniqueId); + LogMessages.LogFailedToRepairDomainObjectSnapshot(log, GetType(), UniqueId, ex); } } diff --git a/backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs b/backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs index 2e0b0538d0..9138dec950 100644 --- a/backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs +++ b/backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs @@ -20,7 +20,7 @@ public async Task HandleAsync(CommandContext context, NextDelegate next, { if (log.IsEnabled(LogLevel.Debug)) { - log.LogDebug("Command {command} with ID {id} started.", type, context.ContextId); + LogMessages.LogCommandStarted(log, type, context.ContextId); } var watch = ValueStopwatch.StartNew(); @@ -28,22 +28,22 @@ public async Task HandleAsync(CommandContext context, NextDelegate next, { await next(context, ct); - log.LogInformation("Command {command} with ID {id} succeeded.", type, context.ContextId); + LogMessages.LogCommandSucceeded(log, type, context.ContextId); } finally { - log.LogInformation("Command {command} with ID {id} completed after {time}ms.", type, context.ContextId, watch.Stop()); + LogMessages.LogCommandCompleted(log, type, context.ContextId, watch.Stop()); } } catch (Exception ex) { - log.LogError(ex, "Command {command} with ID {id} failed.", type, context.ContextId); + LogMessages.LogCommandFailed(log, type, context.ContextId, ex); throw; } if (!context.IsCompleted) { - log.LogCritical("Command {command} with ID {id} not handled.", type, context.ContextId); + LogMessages.LogCommandNotHandled(log, type, context.ContextId); } } } diff --git a/backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs b/backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs index 93dbb7657d..b212d7f399 100644 --- a/backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs +++ b/backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs @@ -105,7 +105,7 @@ await Parallel.ForEachAsync(batches, ct, async (batch, ct) => } catch (Exception ex) { - log.LogWarning(ex, "Found corrupt domain object of type {type} with ID {id}.", typeof(T), id); + LogMessages.LogFoundCorruptDomainObject(log, typeof(T), id, ex); Interlocked.Increment(ref handlerErrors); } } diff --git a/backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs b/backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs index 66e3db23df..7b6c84fd3f 100644 --- a/backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs +++ b/backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumerProcessor.cs @@ -69,7 +69,7 @@ public virtual async Task CompleteAsync() } catch (Exception ex) { - log.LogCritical(ex, "Failed to complete consumer."); + LogMessages.LogFailedToCompleteConsumer(log, ex); } } @@ -107,7 +107,7 @@ public virtual ValueTask OnErrorAsync(IEventSubscription subscription, Exception if (logWindow.CanRetryAfterFailure()) { - log.LogError(exception, "Failed to handle event."); + LogMessages.LogFailedToHandleEvent(log, exception); } }, State.Position); } @@ -215,8 +215,7 @@ private async ValueTask UpdateAsync(Func action, string? position, [Caller ex = new AggregateException(ex, unsubscribeException); } - log.LogCritical(ex, "Failed to update consumer {consumer} at position {position} from {caller}.", - eventConsumer.Name, position, caller); + LogMessages.LogFailedToUpdateConsumer(log, eventConsumer.Name, position, caller, ex); State = previousState.Stopped(ex); } @@ -233,7 +232,7 @@ private async Task ClearAsync() { if (log.IsEnabled(LogLevel.Debug)) { - log.LogDebug("Event consumer {consumer} reset started", eventConsumer.Name); + LogMessages.LogEventConsumerResetStarted(log, eventConsumer.Name); } var watch = ValueStopwatch.StartNew(); @@ -243,7 +242,7 @@ private async Task ClearAsync() } finally { - log.LogDebug("Event consumer {consumer} reset completed after {time}ms.", eventConsumer.Name, watch.Stop()); + LogMessages.LogEventConsumerResetCompleted(log, eventConsumer.Name, watch.Stop()); } } diff --git a/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs b/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs index c472ab44e5..6d1ae4dbb5 100644 --- a/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs +++ b/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs @@ -88,7 +88,7 @@ private async Task TrackAsync( } catch (Exception ex) { - log.LogError(ex, "Failed to track usage in background."); + LogMessages.LogTrackUsageFailed(log, ex); } finally { diff --git a/backend/src/Squidex.Infrastructure/LogMessages.cs b/backend/src/Squidex.Infrastructure/LogMessages.cs new file mode 100644 index 0000000000..9a5d0bb094 --- /dev/null +++ b/backend/src/Squidex.Infrastructure/LogMessages.cs @@ -0,0 +1,64 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex.Infrastructure; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Debug, Message = "Command {command} with ID {id} started.")] + public static partial void LogCommandStarted(ILogger logger, Type command, DomainId id); + + [LoggerMessage(Level = LogLevel.Information, Message = "Command {command} with ID {id} succeeded.")] + public static partial void LogCommandSucceeded(ILogger logger, Type command, DomainId id); + + [LoggerMessage(Level = LogLevel.Information, Message = "Command {command} with ID {id} completed after {time}ms.")] + public static partial void LogCommandCompleted(ILogger logger, Type command, DomainId id, long time); + + [LoggerMessage(Level = LogLevel.Error, Message = "Command {command} with ID {id} failed.")] + public static partial void LogCommandFailed(ILogger logger, Type command, DomainId id, Exception exception); + + [LoggerMessage(Level = LogLevel.Critical, Message = "Command {command} with ID {id} not handled.")] + public static partial void LogCommandNotHandled(ILogger logger, Type command, DomainId id); + + [LoggerMessage(Level = LogLevel.Critical, Message = "Failed to complete consumer.")] + public static partial void LogFailedToCompleteConsumer(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to handle event.")] + public static partial void LogFailedToHandleEvent(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Critical, Message = "Failed to update consumer {consumer} at position {position} from {caller}.")] + public static partial void LogFailedToUpdateConsumer(ILogger logger, string consumer, string? position, string? caller, Exception exception); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Event consumer {consumer} reset started")] + public static partial void LogEventConsumerResetStarted(ILogger logger, string consumer); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Event consumer {consumer} reset completed after {time}ms.")] + public static partial void LogEventConsumerResetCompleted(ILogger logger, string consumer, long time); + + [LoggerMessage(Level = LogLevel.Information, Message = "Migration {migration} started.")] + public static partial void LogMigrationStarted(ILogger logger, string migration); + + [LoggerMessage(Level = LogLevel.Information, Message = "Migration {migration} completed after {time}ms.")] + public static partial void LogMigrationCompleted(ILogger logger, string migration, long time); + + [LoggerMessage(Level = LogLevel.Critical, Message = "Migration {migration} failed.")] + public static partial void LogMigrationFailed(ILogger logger, string migration, Exception exception); + + [LoggerMessage(Level = LogLevel.Information, Message = "Could not acquire lock to start migrating. Trying again in {time}ms.")] + public static partial void LogMigrationLockRetry(ILogger logger, int time); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to track usage in background.")] + public static partial void LogTrackUsageFailed(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to repair snapshot for domain object of type {type} with ID {id}.")] + public static partial void LogFailedToRepairDomainObjectSnapshot(ILogger logger, Type type, DomainId id, Exception exception); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Found corrupt domain object of type {type} with ID {id}.")] + public static partial void LogFoundCorruptDomainObject(ILogger logger, Type type, DomainId id, Exception exception); +} diff --git a/backend/src/Squidex.Infrastructure/Migrations/Migrator.cs b/backend/src/Squidex.Infrastructure/Migrations/Migrator.cs index 076b36cf12..2604afc1db 100644 --- a/backend/src/Squidex.Infrastructure/Migrations/Migrator.cs +++ b/backend/src/Squidex.Infrastructure/Migrations/Migrator.cs @@ -41,7 +41,7 @@ public async Task MigrateAsync( { var name = migration.ToString()!; - log.LogInformation("Migration {migration} started.", name); + LogMessages.LogMigrationStarted(log, name); try { @@ -49,11 +49,11 @@ public async Task MigrateAsync( await migration.UpdateAsync(ct); - log.LogInformation("Migration {migration} completed after {time}ms.", name, watch.Stop()); + LogMessages.LogMigrationCompleted(log, name, watch.Stop()); } catch (Exception ex) { - log.LogCritical(ex, "Migration {migration} failed.", name); + LogMessages.LogMigrationFailed(log, name, ex); throw new MigrationFailedException(name, ex); } } @@ -76,7 +76,7 @@ private async Task TryLockAsync( { while (!await migrationStatus.TryLockAsync(ct)) { - log.LogInformation("Could not acquire lock to start migrating. Trying again in {time}ms.", LockWaitMs); + LogMessages.LogMigrationLockRetry(log, LockWaitMs); await Task.Delay(LockWaitMs, ct); } } diff --git a/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs b/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs index 5adefecc23..621972e889 100644 --- a/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs +++ b/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs @@ -82,7 +82,7 @@ private async Task TrackAsync( } catch (Exception ex) { - log.LogError(ex, "Failed to track usage in background."); + LogMessages.LogTrackUsageFailed(log, ex); } finally { diff --git a/backend/src/Squidex.Web/ApiExceptionFilterAttribute.cs b/backend/src/Squidex.Web/ApiExceptionFilterAttribute.cs index 4572d907b8..d66e32d314 100644 --- a/backend/src/Squidex.Web/ApiExceptionFilterAttribute.cs +++ b/backend/src/Squidex.Web/ApiExceptionFilterAttribute.cs @@ -34,7 +34,7 @@ public void OnException(ExceptionContext context) { var log = context.HttpContext.RequestServices.GetRequiredService>(); - log.LogError(unhandled, "An unexpected exception has occurred."); + LogMessages.LogUnexpectedException(log, unhandled); } context.Result = GetResult(error); diff --git a/backend/src/Squidex.Web/LogMessages.cs b/backend/src/Squidex.Web/LogMessages.cs new file mode 100644 index 0000000000..f746eb4213 --- /dev/null +++ b/backend/src/Squidex.Web/LogMessages.cs @@ -0,0 +1,35 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; +using Squidex.Infrastructure; + +namespace Squidex.Web; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "An unexpected exception has occurred.")] + public static partial void LogUnexpectedException(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Critical, Message = "Failed to send result.")] + public static partial void LogFailedToSendResult(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Cannot find app with the given name {name}.")] + public static partial void LogCannotFindAppByName(ILogger logger, string name); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Authenticated user has no permission to access the app {name} with ID {id}.")] + public static partial void LogNoPermissionToAccessApp(ILogger logger, DomainId id, string name); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Cannot find team with the given id {id}.")] + public static partial void LogCannotFindTeamById(ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Authenticated user has no permission to access the team with ID {id}.")] + public static partial void LogNoPermissionToAccessTeam(ILogger logger, DomainId id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while handling api key.")] + public static partial void LogErrorHandlingApiKey(ILogger logger, Exception exception); +} diff --git a/backend/src/Squidex.Web/Pipeline/ApiKeyHandler.cs b/backend/src/Squidex.Web/Pipeline/ApiKeyHandler.cs index dfc6ffc80a..a3ebb6b5bd 100644 --- a/backend/src/Squidex.Web/Pipeline/ApiKeyHandler.cs +++ b/backend/src/Squidex.Web/Pipeline/ApiKeyHandler.cs @@ -75,7 +75,7 @@ await textIndex.FindUserInfo( } catch (Exception ex) { - Logger.LogError(ex, "Error while handling api key."); + LogMessages.LogErrorHandlingApiKey(Logger, ex); throw; } diff --git a/backend/src/Squidex.Web/Pipeline/AppResolver.cs b/backend/src/Squidex.Web/Pipeline/AppResolver.cs index 0c4f432818..ec73dbdcc1 100644 --- a/backend/src/Squidex.Web/Pipeline/AppResolver.cs +++ b/backend/src/Squidex.Web/Pipeline/AppResolver.cs @@ -41,7 +41,10 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE { var log = context.HttpContext.RequestServices?.GetService>(); - log?.LogWarning("Cannot find app with the given name {name}.", appName); + if (log != null) + { + LogMessages.LogCannotFindAppByName(log, appName); + } context.Result = new NotFoundResult(); return; @@ -97,9 +100,10 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE { var log = context.HttpContext.RequestServices?.GetService>(); - log?.LogWarning("Authenticated user has no permission to access the app {name} with ID {id}.", - app.Id, - app.Name); + if (log != null) + { + LogMessages.LogNoPermissionToAccessApp(log, app.Id, app.Name); + } context.Result = new NotFoundResult(); } diff --git a/backend/src/Squidex.Web/Pipeline/FileCallbackResultExecutor.cs b/backend/src/Squidex.Web/Pipeline/FileCallbackResultExecutor.cs index f0eeadfb9e..15643930eb 100644 --- a/backend/src/Squidex.Web/Pipeline/FileCallbackResultExecutor.cs +++ b/backend/src/Squidex.Web/Pipeline/FileCallbackResultExecutor.cs @@ -54,7 +54,7 @@ public async Task ExecuteAsync(ActionContext context, FileCallbackResult result) response.Headers.Clear(); response.StatusCode = 404; - Logger.LogCritical(new EventId(99), e, "Failed to send result."); + LogMessages.LogFailedToSendResult(Logger, e); } else { diff --git a/backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs b/backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs index c099f8080a..a364e51a29 100644 --- a/backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs +++ b/backend/src/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs @@ -37,7 +37,7 @@ public async Task InvokeAsync(HttpContext context, IActionResultExecutor>(); - log?.LogWarning("Cannot find team with the given id {id}.", teamId); + if (log != null) + { + LogMessages.LogCannotFindTeamById(log, teamId); + } context.Result = new NotFoundResult(); return; @@ -69,7 +72,10 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE { var log = context.HttpContext.RequestServices?.GetService>(); - log?.LogWarning("Authenticated user has no permission to access the team with ID {id}.", team.Id); + if (log != null) + { + LogMessages.LogNoPermissionToAccessTeam(log, team.Id); + } context.Result = new NotFoundResult(); } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs b/backend/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs index 4ca1d1dbfb..8be988c829 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs @@ -98,7 +98,7 @@ public async Task GetUsers(string query) } catch (Exception ex) { - log.LogError(ex, "Failed to return users, returning empty results."); + LogMessages.LogFailedToReturnUsers(log, ex); } return Ok(Array.Empty()); @@ -129,7 +129,7 @@ public async Task GetUser(string id) } catch (Exception ex) { - log.LogError(ex, "Failed to return user, returning empty results."); + LogMessages.LogFailedToReturnUser(log, ex); } return NotFound(); @@ -202,7 +202,7 @@ public async Task GetUserPicture(string id) } catch (Exception ex) { - log.LogError(ex, "Failed to return user picture, returning fallback image."); + LogMessages.LogFailedToReturnUserPicture(log, ex); } return new FileStreamResult(new MemoryStream(AvatarBytes), "image/png"); diff --git a/backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs b/backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs index 4cdea2c1d1..bc86685d4d 100644 --- a/backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs +++ b/backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs @@ -84,7 +84,7 @@ public async Task InitializeAsync( { var log = serviceProvider.GetRequiredService>(); - log.LogError(ex, "Failed to create administrator."); + LogMessages.LogFailedToCreateAdministrator(log, ex); } } diff --git a/backend/src/Squidex/LogMessages.cs b/backend/src/Squidex/LogMessages.cs new file mode 100644 index 0000000000..973d41ecb9 --- /dev/null +++ b/backend/src/Squidex/LogMessages.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.Extensions.Logging; + +namespace Squidex; + +internal static partial class LogMessages +{ + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to create administrator.")] + public static partial void LogFailedToCreateAdministrator(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to return users, returning empty results.")] + public static partial void LogFailedToReturnUsers(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to return user, returning empty results.")] + public static partial void LogFailedToReturnUser(ILogger logger, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Failed to return user picture, returning fallback image.")] + public static partial void LogFailedToReturnUserPicture(ILogger logger, Exception exception); +} diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Collaboration/EmailUserNotificationsTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Collaboration/EmailUserNotificationsTests.cs index 8b71d077c8..c4b6a018a9 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Collaboration/EmailUserNotificationsTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Collaboration/EmailUserNotificationsTests.cs @@ -27,6 +27,9 @@ public class EmailUserNotificationsTests : GivenContext public EmailUserNotificationsTests() { + A.CallTo(() => log.IsEnabled(A._)) + .Returns(true); + A.CallTo(() => urlGenerator.UI()) .Returns("my-ui"); diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Invitation/InvitationEventConsumerTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Invitation/InvitationEventConsumerTests.cs index 6358e43dbc..15101a0d01 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Invitation/InvitationEventConsumerTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Invitation/InvitationEventConsumerTests.cs @@ -34,6 +34,9 @@ public class InvitationEventConsumerTests : GivenContext public InvitationEventConsumerTests() { + A.CallTo(() => log.IsEnabled(A._)) + .Returns(true); + A.CallTo(() => userNotifications.IsActive) .Returns(true); diff --git a/backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs index bafbe59bb5..36fe892f7f 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs @@ -75,6 +75,9 @@ public MigratorTests() { ct = cts.Token; + A.CallTo(() => log.IsEnabled(A._)) + .Returns(true); + A.CallTo(() => path.GetNext(A._)) .ReturnsLazily((int version) => {