From 0071741c3186d4b6c01ef9cf38db7cb69214fca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Sat, 10 Jan 2026 17:50:17 +0100 Subject: [PATCH 1/2] Add loggers --- .../Documents/CreateDocumentEndpoint.cs | 7 ++-- .../Documents/GetDocumentPdfEndpoint.cs | 13 +++++-- .../Helpers/ApplicationUrlProvider.cs | 6 ++-- .../Helpers/ApplicationUrlProviderLogger.cs | 14 ++++++++ src/Turnierplan.App/Helpers/DeletionHelper.cs | 8 ++--- .../Helpers/DeletionHelperLogger.cs | 17 ++++++++++ .../Security/SigningKeyProvider.cs | 3 +- .../Security/SigningKeyProviderLogger.cs | 14 ++++++++ src/Turnierplan.Dal/TurnierplanContext.cs | 10 +++--- .../TurnierplanContextLogger.cs | 22 ++++++++++++ .../Azure/AzureImageStorage.cs | 18 +++++----- .../Azure/AzureImageStorageLogger.cs | 34 +++++++++++++++++++ .../Local/LocalImageStorage.cs | 16 ++++----- .../Local/LocalImageStorageLogger.cs | 31 +++++++++++++++++ .../S3/S3ImageStorage.cs | 12 +++---- .../S3/S3ImageStorageLogger.cs | 25 ++++++++++++++ .../LocalizationProvider.cs | 10 +++--- .../LocalizationProviderLogger.cs | 22 ++++++++++++ 18 files changed, 236 insertions(+), 46 deletions(-) create mode 100644 src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs create mode 100644 src/Turnierplan.App/Helpers/DeletionHelperLogger.cs create mode 100644 src/Turnierplan.App/Security/SigningKeyProviderLogger.cs create mode 100644 src/Turnierplan.Dal/TurnierplanContextLogger.cs create mode 100644 src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs create mode 100644 src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs create mode 100644 src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs create mode 100644 src/Turnierplan.Localization/LocalizationProviderLogger.cs diff --git a/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs b/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs index a05a4b53..63d6ddfd 100644 --- a/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs +++ b/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs @@ -11,7 +11,7 @@ namespace Turnierplan.App.Endpoints.Documents; -internal sealed class CreateDocumentEndpoint : EndpointBase +internal sealed partial class CreateDocumentEndpoint : EndpointBase { protected override HttpMethod Method => HttpMethod.Post; @@ -53,7 +53,7 @@ private static async Task Handle( if (!documentTypeRegistry.TryGetDocumentDefaultConfiguration(request.Type, out var configuration)) { - logger.LogCritical("Could not get the default document configuration for document type {DocumentType}.", request.Type); + CouldNotGetDefaultDocumentConfiguration(logger, request.Type); return Results.InternalServerError(); } @@ -85,4 +85,7 @@ private Validator() .NotEmpty(); } } + + [LoggerMessage(LogLevel.Critical, "Could not get the default document configuration for document type {DocumentType}.", EventId = 100)] + private static partial void CouldNotGetDefaultDocumentConfiguration(ILogger logger, DocumentType documentType); } diff --git a/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs b/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs index 7c3187fb..723ec6d0 100644 --- a/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs +++ b/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Turnierplan.App.OpenApi; using Turnierplan.App.Security; +using Turnierplan.Core.Document; using Turnierplan.Core.PublicId; using Turnierplan.Dal.Extensions; using Turnierplan.Dal.Repositories; @@ -10,7 +11,7 @@ namespace Turnierplan.App.Endpoints.Documents; -internal sealed class GetDocumentPdfEndpoint : EndpointBase +internal sealed partial class GetDocumentPdfEndpoint : EndpointBase { protected override HttpMethod Method => HttpMethod.Get; @@ -59,7 +60,7 @@ private static async Task Handle( if (!documentTypeRegistry.TryParseDocumentConfiguration(document.Type, document.Configuration, out var configuration)) { - logger.LogError("Failed to parse the document configuration of document with type '{DocumentType}'.", document.Type); + FailedToParseDocumentConfiguration(logger, document.Type); return Results.InternalServerError(); } @@ -68,7 +69,7 @@ private static async Task Handle( if (renderer is null) { - logger.LogCritical("No document renderer available for document type '{DocumentType}'.", document.Type); + NoRendererAvailableForDocumentType(logger, document.Type); return Results.InternalServerError(); } @@ -95,4 +96,10 @@ private static async Task Handle( return Results.File(stream.ToArray(), "application/pdf"); } + + [LoggerMessage(LogLevel.Error, "Failed to parse the document configuration of document with type '{DocumentType}'.", EventId = 100)] + private static partial void FailedToParseDocumentConfiguration(ILogger logger, DocumentType documentType); + + [LoggerMessage(LogLevel.Critical, "No document renderer available for document type '{DocumentType}'.", EventId = 101)] + private static partial void NoRendererAvailableForDocumentType(ILogger logger, DocumentType documentType); } diff --git a/src/Turnierplan.App/Helpers/ApplicationUrlProvider.cs b/src/Turnierplan.App/Helpers/ApplicationUrlProvider.cs index dbe856f3..df5ab782 100644 --- a/src/Turnierplan.App/Helpers/ApplicationUrlProvider.cs +++ b/src/Turnierplan.App/Helpers/ApplicationUrlProvider.cs @@ -7,12 +7,12 @@ namespace Turnierplan.App.Helpers; internal sealed class ApplicationUrlProvider : IApplicationUrlProvider { private readonly IOptionsMonitor _options; - private readonly ILogger _logger; + private readonly ApplicationUrlProviderLogger _logger; public ApplicationUrlProvider(IOptionsMonitor options, ILogger logger) { _options = options; - _logger = logger; + _logger = new ApplicationUrlProviderLogger(logger); } public string GetApplicationUrl() @@ -21,7 +21,7 @@ public string GetApplicationUrl() if (string.IsNullOrWhiteSpace(url)) { - _logger.LogWarning("The ApplicationUrl is not specified. Please check your application configuration."); + _logger.ApplicationUrlNotSpecified(); return string.Empty; } diff --git a/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs b/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs new file mode 100644 index 00000000..338dc598 --- /dev/null +++ b/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs @@ -0,0 +1,14 @@ +namespace Turnierplan.App.Helpers; + +internal sealed partial class ApplicationUrlProviderLogger +{ + private readonly ILogger _logger; + + public ApplicationUrlProviderLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Warning, "The 'ApplicationUrl' is not specified. Please check your application configuration.", EventId = 100)] + public partial void ApplicationUrlNotSpecified(); +} diff --git a/src/Turnierplan.App/Helpers/DeletionHelper.cs b/src/Turnierplan.App/Helpers/DeletionHelper.cs index e4b51301..3fff5884 100644 --- a/src/Turnierplan.App/Helpers/DeletionHelper.cs +++ b/src/Turnierplan.App/Helpers/DeletionHelper.cs @@ -17,7 +17,7 @@ internal sealed class DeletionHelper : IDeletionHelper private readonly IPlanningRealmRepository _planningRealmRepository; private readonly IImageRepository _imageRepository; private readonly IImageStorage _imageStorage; - private readonly ILogger _logger; + private readonly DeletionHelperLogger _logger; public DeletionHelper( IOrganizationRepository organizationRepository, @@ -34,7 +34,7 @@ public DeletionHelper( _planningRealmRepository = planningRealmRepository; _imageRepository = imageRepository; _imageStorage = imageStorage; - _logger = logger; + _logger = new DeletionHelperLogger(logger); } public async Task DeleteOrganizationAsync(Organization organization, CancellationToken cancellationToken) @@ -57,14 +57,14 @@ public async Task DeleteOrganizationAsync(Organization organization, Cance } catch (Exception ex) { - _logger.LogError(ex, "Image with id '{ImageId}' was successfully deleted from image storage but the deletion from the database failed.", image.Id); + _logger.ImageDeletedButDatabaseRemovalFailed(ex, image.Id); return false; } } else { - _logger.LogError("Failed to delete image with id '{ImageId}' from image storage while deleting organization with id '{OrganizationId}'.", image.Id, organization.Id); + _logger.ImageDeletionFromStorageFailed(image.Id, organization.Id); hasNonDeletedImages = true; } diff --git a/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs b/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs new file mode 100644 index 00000000..28dbc359 --- /dev/null +++ b/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs @@ -0,0 +1,17 @@ +namespace Turnierplan.App.Helpers; + +internal sealed partial class DeletionHelperLogger +{ + private readonly ILogger _logger; + + public DeletionHelperLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Error, "Image with id '{ImageId}' was successfully deleted from image storage but the deletion from the database failed.", EventId = 100)] + public partial void ImageDeletedButDatabaseRemovalFailed(Exception exception, long imageId); + + [LoggerMessage(LogLevel.Error, "Failed to delete image with id '{ImageId}' from image storage while deleting organization with id '{OrganizationId}'.", EventId = 101)] + public partial void ImageDeletionFromStorageFailed(long imageId, long organizationId); +} diff --git a/src/Turnierplan.App/Security/SigningKeyProvider.cs b/src/Turnierplan.App/Security/SigningKeyProvider.cs index a5d3936c..11ac5187 100644 --- a/src/Turnierplan.App/Security/SigningKeyProvider.cs +++ b/src/Turnierplan.App/Security/SigningKeyProvider.cs @@ -26,7 +26,8 @@ public SigningKeyProvider(IOptions options, ILogger _logger; + + public SigningKeyProviderLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Critical, "The directory for identity storage does not exist and could not be created.", EventId = 100)] + public partial void IdentityDirectoryCreationFailed(); +} diff --git a/src/Turnierplan.Dal/TurnierplanContext.cs b/src/Turnierplan.Dal/TurnierplanContext.cs index 8c8a25eb..9f55fc1e 100644 --- a/src/Turnierplan.Dal/TurnierplanContext.cs +++ b/src/Turnierplan.Dal/TurnierplanContext.cs @@ -20,14 +20,14 @@ public sealed class TurnierplanContext : DbContext, IUnitOfWork { public const string Schema = "turnierplan"; - private readonly ILogger _logger; + private readonly TurnierplanContextLogger _logger; private IDbContextTransaction? _activeTransaction; public TurnierplanContext(DbContextOptions options, ILogger logger) : base(options) { - _logger = logger; + _logger = new TurnierplanContextLogger(logger); } public DbSet ApiKeys { get; set; } = null!; @@ -95,7 +95,7 @@ public async Task BeginTransactionAsync() throw new InvalidOperationException("Transaction already started."); } - _logger.LogInformation("Beginning database transaction"); + _logger.BeginningTransaction(); _activeTransaction = await Database.BeginTransactionAsync(); } @@ -107,7 +107,7 @@ public async Task CommitTransactionAsync() throw new InvalidOperationException("Transaction not started."); } - _logger.LogInformation("Committing database transaction"); + _logger.CommittingTransaction(); await _activeTransaction.CommitAsync(); await _activeTransaction.DisposeAsync(); @@ -122,7 +122,7 @@ public async Task RollbackTransactionAsync() throw new InvalidOperationException("Transaction not started."); } - _logger.LogInformation("Rolling back database transaction"); + _logger.RollingBackTransaction(); await _activeTransaction.RollbackAsync(); await _activeTransaction.DisposeAsync(); diff --git a/src/Turnierplan.Dal/TurnierplanContextLogger.cs b/src/Turnierplan.Dal/TurnierplanContextLogger.cs new file mode 100644 index 00000000..5b085b9f --- /dev/null +++ b/src/Turnierplan.Dal/TurnierplanContextLogger.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.Logging; + +namespace Turnierplan.Dal; + +internal sealed partial class TurnierplanContextLogger +{ + private readonly ILogger _logger; + + public TurnierplanContextLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Information, "Beginning database transaction", EventId = 100)] + public partial void BeginningTransaction(); + + [LoggerMessage(LogLevel.Information, "Committing database transaction", EventId = 101)] + public partial void CommittingTransaction(); + + [LoggerMessage(LogLevel.Information, "Rolling back database transaction", EventId = 102)] + public partial void RollingBackTransaction(); +} diff --git a/src/Turnierplan.ImageStorage/Azure/AzureImageStorage.cs b/src/Turnierplan.ImageStorage/Azure/AzureImageStorage.cs index 0ab2f9e5..f524664b 100644 --- a/src/Turnierplan.ImageStorage/Azure/AzureImageStorage.cs +++ b/src/Turnierplan.ImageStorage/Azure/AzureImageStorage.cs @@ -10,14 +10,14 @@ namespace Turnierplan.ImageStorage.Azure; internal sealed class AzureImageStorage : IImageStorage { - private readonly ILogger _logger; + private readonly AzureImageStorageLogger _logger; private readonly BlobContainerClient _client; private readonly string _storageAccountUrl; private readonly string _containerName; public AzureImageStorage(IOptions options, ILogger logger) { - _logger = logger; + _logger = new AzureImageStorageLogger(logger); ArgumentException.ThrowIfNullOrWhiteSpace(options.Value.StorageAccountName); ArgumentException.ThrowIfNullOrWhiteSpace(options.Value.ContainerName); @@ -25,7 +25,7 @@ public AzureImageStorage(IOptions options, ILogger options, ILogger options, ILogger SaveImageAsync(Image image, MemoryStream imageData) } catch (Exception ex) { - _logger.LogError(ex, "Failed to upload image '{BlobName}' to Azure Blob Storage because of an exception.", blobName); + _logger.FailedToUploadImage(ex, blobName); } return false; @@ -110,7 +110,7 @@ public async Task GetImageAsync(Image image) } catch (Exception ex) { - _logger.LogError(ex, "Failed to read image '{BlobName}' from Azure Blob Storage because of an exception.", blobName); + _logger.FailedToReadImage(ex, blobName); throw new InvalidOperationException("Failed to read image from Azure Blob Storage.", ex); } @@ -129,7 +129,7 @@ public async Task DeleteImageAsync(Image image) } catch (Exception ex) { - _logger.LogError(ex, "Failed to delete image '{BlobName}' from Azure Blob Storage because of an exception.", blobName); + _logger.FailedToDeleteImage(ex, blobName); } return false; diff --git a/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs b/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs new file mode 100644 index 00000000..bce75ddd --- /dev/null +++ b/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Logging; + +namespace Turnierplan.ImageStorage.Azure; + +internal sealed partial class AzureImageStorageLogger +{ + private readonly ILogger _logger; + + public AzureImageStorageLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Information, "Initializing Azure Blob Storage client for storage account '{StorageAccountUrl}'.", EventId = 100)] + public partial void InitializingAzureBlobStorageClient(string storageAccountUrl); + + [LoggerMessage(LogLevel.Information, "Using account key authentication for Azure Blob Storage", EventId = 101)] + public partial void UsingAccountKeyAuthentication(); + + [LoggerMessage(LogLevel.Information, "Using ClientSecretCredential for Azure Blob Storage", EventId = 102)] + public partial void UsingClientSecretCredential(); + + [LoggerMessage(LogLevel.Information, "Using DefaultAzureCredential for Azure Blob Storage", EventId = 103)] + public partial void UsingDefaultAzureCredential(); + + [LoggerMessage(LogLevel.Error, "Failed to upload image '{BlobName}' to Azure Blob Storage because of an exception.", EventId = 104)] + public partial void FailedToUploadImage(Exception exception, string blobName); + + [LoggerMessage(LogLevel.Error, "Failed to read image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 105)] + public partial void FailedToReadImage(Exception exception, string blobName); + + [LoggerMessage(LogLevel.Error, "Failed to delete image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 106)] + public partial void FailedToDeleteImage(Exception exception, string blobName); +} diff --git a/src/Turnierplan.ImageStorage/Local/LocalImageStorage.cs b/src/Turnierplan.ImageStorage/Local/LocalImageStorage.cs index 85be3a5a..ee449df6 100644 --- a/src/Turnierplan.ImageStorage/Local/LocalImageStorage.cs +++ b/src/Turnierplan.ImageStorage/Local/LocalImageStorage.cs @@ -9,23 +9,23 @@ namespace Turnierplan.ImageStorage.Local; internal sealed class LocalImageStorage : ILocalImageStorage { - private readonly ILogger _logger; + private readonly LocalImageStorageLogger _logger; private readonly string _storagePath; public LocalImageStorage(ILogger logger, IOptions options) { - _logger = logger; + _logger = new LocalImageStorageLogger(logger); ArgumentException.ThrowIfNullOrWhiteSpace(options.Value.StoragePath); _storagePath = Path.GetFullPath(options.Value.StoragePath); - _logger.LogInformation("Using the following directory for local image storage: '{LocalImageStoragePath}'", _storagePath); + _logger.UsingDirectoryForLocalImageStorage(_storagePath); Directory.CreateDirectory(_storagePath); if (!Directory.Exists(_storagePath)) { - _logger.LogCritical("The directory for local image storage does not exist and could not be created."); + _logger.DirectoryCouldNotBeCreated(); } } @@ -50,13 +50,13 @@ public Task SaveImageAsync(Image image, MemoryStream imageData) if (!Directory.Exists(imageDirectoryPath)) { - _logger.LogCritical("The directory for the image could not be created: '{ImageDirectory}'.", imageDirectoryPath); + _logger.DirectoryForImageCouldNotBeCreated(imageDirectoryPath); return Task.FromResult(false); } } - _logger.LogDebug("Writing image to: {FilePath}", filePath); + _logger.WritingImageToFile(filePath); using var destination = new FileStream(filePath, FileMode.Create); imageData.CopyTo(destination); @@ -65,7 +65,7 @@ public Task SaveImageAsync(Image image, MemoryStream imageData) } catch (Exception ex) { - _logger.LogError(ex, "Failed to save image to file to '{FilePath}'.", filePath); + _logger.FailedToWriteImage(ex, filePath); return Task.FromResult(false); } @@ -86,7 +86,7 @@ public Task DeleteImageAsync(Image image) } catch (Exception ex) { - _logger.LogError(ex, "Failed to delete image file '{FilePath}'.", filePath); + _logger.FailedToDeleteImage(ex, filePath); return Task.FromResult(false); } diff --git a/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs b/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs new file mode 100644 index 00000000..933f33e9 --- /dev/null +++ b/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Logging; + +namespace Turnierplan.ImageStorage.Local; + +internal sealed partial class LocalImageStorageLogger +{ + private readonly ILogger _logger; + + public LocalImageStorageLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Information, "Using the following directory for local image storage: '{LocalImageStoragePath}'", EventId = 100)] + public partial void UsingDirectoryForLocalImageStorage(string localImageStoragePath); + + [LoggerMessage(LogLevel.Critical, "The directory for local image storage does not exist and could not be created.", EventId = 101)] + public partial void DirectoryCouldNotBeCreated(); + + [LoggerMessage(LogLevel.Critical, "The directory for the image could not be created: '{ImageDirectory}'.", EventId = 102)] + public partial void DirectoryForImageCouldNotBeCreated(string imageDirectory); + + [LoggerMessage(LogLevel.Debug, "Writing image to: {FilePath}", EventId = 103)] + public partial void WritingImageToFile(string filePath); + + [LoggerMessage(LogLevel.Error, "Failed to save image to file to '{FilePath}'.", EventId = 104)] + public partial void FailedToWriteImage(Exception exception, string filePath); + + [LoggerMessage(LogLevel.Error, "Failed to delete image file '{FilePath}'.", EventId = 105)] + public partial void FailedToDeleteImage(Exception exception, string filePath); +} diff --git a/src/Turnierplan.ImageStorage/S3/S3ImageStorage.cs b/src/Turnierplan.ImageStorage/S3/S3ImageStorage.cs index f1a3705a..f12cb2cc 100644 --- a/src/Turnierplan.ImageStorage/S3/S3ImageStorage.cs +++ b/src/Turnierplan.ImageStorage/S3/S3ImageStorage.cs @@ -11,7 +11,7 @@ namespace Turnierplan.ImageStorage.S3; internal sealed class S3ImageStorage : IImageStorage { - private readonly ILogger _logger; + private readonly S3ImageStorageLogger _logger; private readonly AmazonS3Client _client; private readonly string _bucketName; @@ -21,7 +21,7 @@ public S3ImageStorage(IOptions options, ILogger SaveImageAsync(Image image, MemoryStream imageData) return true; } - _logger.LogError("Failed to upload image '{ObjectKey}' to S3. Result status code: {StatusCode}", objectKey, (int)response.HttpStatusCode); + _logger.FailedToUploadImage(objectKey, (int)response.HttpStatusCode); } catch (Exception ex) { - _logger.LogError(ex, "Failed to upload image '{ObjectKey}' to S3 because of an exception.", objectKey); + _logger.FailedToUploadImage(ex, objectKey); } return false; @@ -112,7 +112,7 @@ public async Task GetImageAsync(Image image) return response.ResponseStream; } - _logger.LogError("Failed to read image '{ObjectKey}' from S3. Result status code: {StatusCode}", objectKey, (int)response.HttpStatusCode); + _logger.FailedToReadImage(objectKey, (int)response.HttpStatusCode); throw new InvalidOperationException($"Failed to read image from S3. Status code: {response.HttpStatusCode}"); } @@ -138,7 +138,7 @@ public async Task DeleteImageAsync(Image image) } catch (Exception ex) { - _logger.LogError(ex, "Failed to delete image '{ObjectKey}' from S3 because of an exception.", objectKey); + _logger.FailedToDeleteImage(ex, objectKey); } return false; diff --git a/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs b/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs new file mode 100644 index 00000000..621e83f8 --- /dev/null +++ b/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; + +namespace Turnierplan.ImageStorage.S3; + +internal sealed partial class S3ImageStorageLogger +{ + private readonly ILogger _logger; + + public S3ImageStorageLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3. Result status code: {StatusCode}", EventId = 100)] + public partial void FailedToUploadImage(string objectKey, int statusCode); + + [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3 because of an exception.", EventId = 101)] + public partial void FailedToUploadImage(Exception exception, string objectKey); + + [LoggerMessage(LogLevel.Error, "Failed to read image '{ObjectKey}' from S3. Result status code: {StatusCode}", EventId = 102)] + public partial void FailedToReadImage(string objectKey, int statusCode); + + [LoggerMessage(LogLevel.Error, "Failed to delete image '{ObjectKey}' from S3 because of an exception.", EventId = 103)] + public partial void FailedToDeleteImage(Exception exception, string objectKey); +} diff --git a/src/Turnierplan.Localization/LocalizationProvider.cs b/src/Turnierplan.Localization/LocalizationProvider.cs index ba1a1e27..373a415d 100644 --- a/src/Turnierplan.Localization/LocalizationProvider.cs +++ b/src/Turnierplan.Localization/LocalizationProvider.cs @@ -8,12 +8,12 @@ namespace Turnierplan.Localization; internal sealed partial class LocalizationProvider : ILocalizationProvider { - private readonly ILogger _logger; + private readonly LocalizationProviderLogger _logger; private readonly Dictionary _cache = []; public LocalizationProvider(ILogger logger) { - _logger = logger; + _logger = new LocalizationProviderLogger(logger); LoadLanguages(); } @@ -47,7 +47,7 @@ private void LoadLanguages() if (stream is null) { - _logger.LogError("Stream for translations file '{LocalizationResourceName}' is null.", resourceName); + _logger.LocalizationResourceStreamIsNull(resourceName); continue; } @@ -55,7 +55,7 @@ private void LoadLanguages() if (culture is null) { - _logger.LogWarning("Could not find CultureInfo for language code '{LanguageCode}'. Falling back to 'InvariantCulture'.", languageCode); + _logger.CouldNotFindCultureInfoForLanguageCode(languageCode); culture = CultureInfo.InvariantCulture; } @@ -64,7 +64,7 @@ private void LoadLanguages() } catch (Exception ex) { - _logger.LogError(ex, "Failed to load translations for language with code '{LanguageCode}'.", languageCode); + _logger.FailedToLoadTranslationsForLanguage(ex, languageCode); } } } diff --git a/src/Turnierplan.Localization/LocalizationProviderLogger.cs b/src/Turnierplan.Localization/LocalizationProviderLogger.cs new file mode 100644 index 00000000..15965775 --- /dev/null +++ b/src/Turnierplan.Localization/LocalizationProviderLogger.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.Logging; + +namespace Turnierplan.Localization; + +internal sealed partial class LocalizationProviderLogger +{ + private readonly ILogger _logger; + + public LocalizationProviderLogger(ILogger logger) + { + _logger = logger; + } + + [LoggerMessage(LogLevel.Error, "Stream for translations file '{LocalizationResourceName}' is null.", EventId = 100)] + public partial void LocalizationResourceStreamIsNull(string localizationResourceName); + + [LoggerMessage(LogLevel.Warning, "Could not find CultureInfo for language code '{LanguageCode}'. Falling back to 'InvariantCulture'.", EventId = 101)] + public partial void CouldNotFindCultureInfoForLanguageCode(string languageCode); + + [LoggerMessage(LogLevel.Error, "Failed to load translations for language with code '{LanguageCode}'.", EventId = 102)] + public partial void FailedToLoadTranslationsForLanguage(Exception exception, string languageCode); +} From c74ae11dedd1a7fd64c6a1c65778d0b967d0473e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Sat, 10 Jan 2026 17:51:48 +0100 Subject: [PATCH 2/2] Start 101 --- .../Endpoints/Documents/CreateDocumentEndpoint.cs | 2 +- .../Endpoints/Documents/GetDocumentPdfEndpoint.cs | 4 ++-- .../Helpers/ApplicationUrlProviderLogger.cs | 2 +- .../Helpers/DeletionHelperLogger.cs | 4 ++-- .../Security/SigningKeyProviderLogger.cs | 2 +- src/Turnierplan.Dal/TurnierplanContextLogger.cs | 6 +++--- .../Azure/AzureImageStorageLogger.cs | 14 +++++++------- .../Local/LocalImageStorageLogger.cs | 12 ++++++------ .../S3/S3ImageStorageLogger.cs | 8 ++++---- .../LocalizationProviderLogger.cs | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs b/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs index 63d6ddfd..e2faad29 100644 --- a/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs +++ b/src/Turnierplan.App/Endpoints/Documents/CreateDocumentEndpoint.cs @@ -86,6 +86,6 @@ private Validator() } } - [LoggerMessage(LogLevel.Critical, "Could not get the default document configuration for document type {DocumentType}.", EventId = 100)] + [LoggerMessage(LogLevel.Critical, "Could not get the default document configuration for document type {DocumentType}.", EventId = 101)] private static partial void CouldNotGetDefaultDocumentConfiguration(ILogger logger, DocumentType documentType); } diff --git a/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs b/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs index 723ec6d0..a8a9dfe5 100644 --- a/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs +++ b/src/Turnierplan.App/Endpoints/Documents/GetDocumentPdfEndpoint.cs @@ -97,9 +97,9 @@ private static async Task Handle( return Results.File(stream.ToArray(), "application/pdf"); } - [LoggerMessage(LogLevel.Error, "Failed to parse the document configuration of document with type '{DocumentType}'.", EventId = 100)] + [LoggerMessage(LogLevel.Error, "Failed to parse the document configuration of document with type '{DocumentType}'.", EventId = 101)] private static partial void FailedToParseDocumentConfiguration(ILogger logger, DocumentType documentType); - [LoggerMessage(LogLevel.Critical, "No document renderer available for document type '{DocumentType}'.", EventId = 101)] + [LoggerMessage(LogLevel.Critical, "No document renderer available for document type '{DocumentType}'.", EventId = 102)] private static partial void NoRendererAvailableForDocumentType(ILogger logger, DocumentType documentType); } diff --git a/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs b/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs index 338dc598..60121e08 100644 --- a/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs +++ b/src/Turnierplan.App/Helpers/ApplicationUrlProviderLogger.cs @@ -9,6 +9,6 @@ public ApplicationUrlProviderLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Warning, "The 'ApplicationUrl' is not specified. Please check your application configuration.", EventId = 100)] + [LoggerMessage(LogLevel.Warning, "The 'ApplicationUrl' is not specified. Please check your application configuration.", EventId = 101)] public partial void ApplicationUrlNotSpecified(); } diff --git a/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs b/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs index 28dbc359..18d70979 100644 --- a/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs +++ b/src/Turnierplan.App/Helpers/DeletionHelperLogger.cs @@ -9,9 +9,9 @@ public DeletionHelperLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Error, "Image with id '{ImageId}' was successfully deleted from image storage but the deletion from the database failed.", EventId = 100)] + [LoggerMessage(LogLevel.Error, "Image with id '{ImageId}' was successfully deleted from image storage but the deletion from the database failed.", EventId = 101)] public partial void ImageDeletedButDatabaseRemovalFailed(Exception exception, long imageId); - [LoggerMessage(LogLevel.Error, "Failed to delete image with id '{ImageId}' from image storage while deleting organization with id '{OrganizationId}'.", EventId = 101)] + [LoggerMessage(LogLevel.Error, "Failed to delete image with id '{ImageId}' from image storage while deleting organization with id '{OrganizationId}'.", EventId = 102)] public partial void ImageDeletionFromStorageFailed(long imageId, long organizationId); } diff --git a/src/Turnierplan.App/Security/SigningKeyProviderLogger.cs b/src/Turnierplan.App/Security/SigningKeyProviderLogger.cs index 02a2fbfc..002e630a 100644 --- a/src/Turnierplan.App/Security/SigningKeyProviderLogger.cs +++ b/src/Turnierplan.App/Security/SigningKeyProviderLogger.cs @@ -9,6 +9,6 @@ public SigningKeyProviderLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Critical, "The directory for identity storage does not exist and could not be created.", EventId = 100)] + [LoggerMessage(LogLevel.Critical, "The directory for identity storage does not exist and could not be created.", EventId = 101)] public partial void IdentityDirectoryCreationFailed(); } diff --git a/src/Turnierplan.Dal/TurnierplanContextLogger.cs b/src/Turnierplan.Dal/TurnierplanContextLogger.cs index 5b085b9f..03b437b7 100644 --- a/src/Turnierplan.Dal/TurnierplanContextLogger.cs +++ b/src/Turnierplan.Dal/TurnierplanContextLogger.cs @@ -11,12 +11,12 @@ public TurnierplanContextLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Information, "Beginning database transaction", EventId = 100)] + [LoggerMessage(LogLevel.Information, "Beginning database transaction", EventId = 101)] public partial void BeginningTransaction(); - [LoggerMessage(LogLevel.Information, "Committing database transaction", EventId = 101)] + [LoggerMessage(LogLevel.Information, "Committing database transaction", EventId = 102)] public partial void CommittingTransaction(); - [LoggerMessage(LogLevel.Information, "Rolling back database transaction", EventId = 102)] + [LoggerMessage(LogLevel.Information, "Rolling back database transaction", EventId = 103)] public partial void RollingBackTransaction(); } diff --git a/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs b/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs index bce75ddd..de0f7bf5 100644 --- a/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs +++ b/src/Turnierplan.ImageStorage/Azure/AzureImageStorageLogger.cs @@ -11,24 +11,24 @@ public AzureImageStorageLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Information, "Initializing Azure Blob Storage client for storage account '{StorageAccountUrl}'.", EventId = 100)] + [LoggerMessage(LogLevel.Information, "Initializing Azure Blob Storage client for storage account '{StorageAccountUrl}'.", EventId = 101)] public partial void InitializingAzureBlobStorageClient(string storageAccountUrl); - [LoggerMessage(LogLevel.Information, "Using account key authentication for Azure Blob Storage", EventId = 101)] + [LoggerMessage(LogLevel.Information, "Using account key authentication for Azure Blob Storage", EventId = 102)] public partial void UsingAccountKeyAuthentication(); - [LoggerMessage(LogLevel.Information, "Using ClientSecretCredential for Azure Blob Storage", EventId = 102)] + [LoggerMessage(LogLevel.Information, "Using ClientSecretCredential for Azure Blob Storage", EventId = 103)] public partial void UsingClientSecretCredential(); - [LoggerMessage(LogLevel.Information, "Using DefaultAzureCredential for Azure Blob Storage", EventId = 103)] + [LoggerMessage(LogLevel.Information, "Using DefaultAzureCredential for Azure Blob Storage", EventId = 104)] public partial void UsingDefaultAzureCredential(); - [LoggerMessage(LogLevel.Error, "Failed to upload image '{BlobName}' to Azure Blob Storage because of an exception.", EventId = 104)] + [LoggerMessage(LogLevel.Error, "Failed to upload image '{BlobName}' to Azure Blob Storage because of an exception.", EventId = 105)] public partial void FailedToUploadImage(Exception exception, string blobName); - [LoggerMessage(LogLevel.Error, "Failed to read image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 105)] + [LoggerMessage(LogLevel.Error, "Failed to read image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 106)] public partial void FailedToReadImage(Exception exception, string blobName); - [LoggerMessage(LogLevel.Error, "Failed to delete image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 106)] + [LoggerMessage(LogLevel.Error, "Failed to delete image '{BlobName}' from Azure Blob Storage because of an exception.", EventId = 107)] public partial void FailedToDeleteImage(Exception exception, string blobName); } diff --git a/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs b/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs index 933f33e9..8a93ae51 100644 --- a/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs +++ b/src/Turnierplan.ImageStorage/Local/LocalImageStorageLogger.cs @@ -11,21 +11,21 @@ public LocalImageStorageLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Information, "Using the following directory for local image storage: '{LocalImageStoragePath}'", EventId = 100)] + [LoggerMessage(LogLevel.Information, "Using the following directory for local image storage: '{LocalImageStoragePath}'", EventId = 101)] public partial void UsingDirectoryForLocalImageStorage(string localImageStoragePath); - [LoggerMessage(LogLevel.Critical, "The directory for local image storage does not exist and could not be created.", EventId = 101)] + [LoggerMessage(LogLevel.Critical, "The directory for local image storage does not exist and could not be created.", EventId = 102)] public partial void DirectoryCouldNotBeCreated(); - [LoggerMessage(LogLevel.Critical, "The directory for the image could not be created: '{ImageDirectory}'.", EventId = 102)] + [LoggerMessage(LogLevel.Critical, "The directory for the image could not be created: '{ImageDirectory}'.", EventId = 103)] public partial void DirectoryForImageCouldNotBeCreated(string imageDirectory); - [LoggerMessage(LogLevel.Debug, "Writing image to: {FilePath}", EventId = 103)] + [LoggerMessage(LogLevel.Debug, "Writing image to: {FilePath}", EventId = 104)] public partial void WritingImageToFile(string filePath); - [LoggerMessage(LogLevel.Error, "Failed to save image to file to '{FilePath}'.", EventId = 104)] + [LoggerMessage(LogLevel.Error, "Failed to save image to file to '{FilePath}'.", EventId = 105)] public partial void FailedToWriteImage(Exception exception, string filePath); - [LoggerMessage(LogLevel.Error, "Failed to delete image file '{FilePath}'.", EventId = 105)] + [LoggerMessage(LogLevel.Error, "Failed to delete image file '{FilePath}'.", EventId = 106)] public partial void FailedToDeleteImage(Exception exception, string filePath); } diff --git a/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs b/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs index 621e83f8..585a7cf4 100644 --- a/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs +++ b/src/Turnierplan.ImageStorage/S3/S3ImageStorageLogger.cs @@ -11,15 +11,15 @@ public S3ImageStorageLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3. Result status code: {StatusCode}", EventId = 100)] + [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3. Result status code: {StatusCode}", EventId = 101)] public partial void FailedToUploadImage(string objectKey, int statusCode); - [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3 because of an exception.", EventId = 101)] + [LoggerMessage(LogLevel.Error, "Failed to upload image '{ObjectKey}' to S3 because of an exception.", EventId = 102)] public partial void FailedToUploadImage(Exception exception, string objectKey); - [LoggerMessage(LogLevel.Error, "Failed to read image '{ObjectKey}' from S3. Result status code: {StatusCode}", EventId = 102)] + [LoggerMessage(LogLevel.Error, "Failed to read image '{ObjectKey}' from S3. Result status code: {StatusCode}", EventId = 103)] public partial void FailedToReadImage(string objectKey, int statusCode); - [LoggerMessage(LogLevel.Error, "Failed to delete image '{ObjectKey}' from S3 because of an exception.", EventId = 103)] + [LoggerMessage(LogLevel.Error, "Failed to delete image '{ObjectKey}' from S3 because of an exception.", EventId = 104)] public partial void FailedToDeleteImage(Exception exception, string objectKey); } diff --git a/src/Turnierplan.Localization/LocalizationProviderLogger.cs b/src/Turnierplan.Localization/LocalizationProviderLogger.cs index 15965775..fb019875 100644 --- a/src/Turnierplan.Localization/LocalizationProviderLogger.cs +++ b/src/Turnierplan.Localization/LocalizationProviderLogger.cs @@ -11,12 +11,12 @@ public LocalizationProviderLogger(ILogger logger) _logger = logger; } - [LoggerMessage(LogLevel.Error, "Stream for translations file '{LocalizationResourceName}' is null.", EventId = 100)] + [LoggerMessage(LogLevel.Error, "Stream for translations file '{LocalizationResourceName}' is null.", EventId = 101)] public partial void LocalizationResourceStreamIsNull(string localizationResourceName); - [LoggerMessage(LogLevel.Warning, "Could not find CultureInfo for language code '{LanguageCode}'. Falling back to 'InvariantCulture'.", EventId = 101)] + [LoggerMessage(LogLevel.Warning, "Could not find CultureInfo for language code '{LanguageCode}'. Falling back to 'InvariantCulture'.", EventId = 102)] public partial void CouldNotFindCultureInfoForLanguageCode(string languageCode); - [LoggerMessage(LogLevel.Error, "Failed to load translations for language with code '{LanguageCode}'.", EventId = 102)] + [LoggerMessage(LogLevel.Error, "Failed to load translations for language with code '{LanguageCode}'.", EventId = 103)] public partial void FailedToLoadTranslationsForLanguage(Exception exception, string languageCode); }