Skip to content

Commit 38b2f2f

Browse files
committed
Simplifies Azure Blob Storage persistence configuration.
Refactors the Azure Blob Storage persistence to streamline its configuration. It removes the direct instantiation of BlobContainerClient within the base class and instead, registers the AzureBlobBodyStoragePersistence class for dependency injection, allowing the constructor to handle the BlobContainerClient creation. Additionally, it ensures that the ContentType metadata stored in Azure Blob Storage is properly encoded and decoded to handle special characters. Also, it adds MessageBodyStorageConnectionStringKey to the configuration keys for both PostgreSQL and SQL Server.
1 parent 4cb7a1c commit 38b2f2f

4 files changed

Lines changed: 22 additions & 14 deletions

File tree

src/ServiceControl.Audit.Persistence.Sql.Core/Abstractions/BaseAuditPersistence.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ protected static void RegisterDataStores(IServiceCollection services, AuditSqlPe
1919
}
2020
else
2121
{
22-
var blobClient = new BlobServiceClient(settings.MessageBodyStorageConnectionString);
23-
var blobContainerClient = blobClient.GetBlobContainerClient("audit-bodies");
24-
services.AddSingleton<IBodyStoragePersistence>(new AzureBlobBodyStoragePersistence(blobContainerClient, settings));
22+
services.AddSingleton<IBodyStoragePersistence, AzureBlobBodyStoragePersistence>();
2523
}
2624
services.AddSingleton<IBodyStorage, BodyStorageFetcher>();
2725
services.AddSingleton<IAuditDataStore, EFAuditDataStore>();

src/ServiceControl.Audit.Persistence.Sql.Core/Implementation/AzureBlobBodyStoragePersistence.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,19 @@ namespace ServiceControl.Audit.Persistence.Sql.Core.Infrastructure;
77
using Azure.Storage.Blobs.Models;
88
using ServiceControl.Audit.Persistence.Sql.Core.Abstractions;
99

10-
public class AzureBlobBodyStoragePersistence(BlobContainerClient blobContainerClient, AuditSqlPersisterSettings settings) : IBodyStoragePersistence
10+
public class AzureBlobBodyStoragePersistence : IBodyStoragePersistence
1111
{
1212
const string FormatVersion = "1";
13+
readonly AuditSqlPersisterSettings settings;
14+
readonly BlobContainerClient blobContainerClient;
15+
16+
public AzureBlobBodyStoragePersistence(AuditSqlPersisterSettings settings)
17+
{
18+
this.settings = settings;
19+
20+
var blobClient = new BlobServiceClient(settings.MessageBodyStorageConnectionString);
21+
blobContainerClient = blobClient.GetBlobContainerClient("audit-bodies");
22+
}
1323

1424
// Blob deletion is handled by Azure Blob Storage lifecycle management policies.
1525
// See: https://learn.microsoft.com/en-us/azure/storage/blobs/lifecycle-management-policy-delete
@@ -31,7 +41,7 @@ public class AzureBlobBodyStoragePersistence(BlobContainerClient blobContainerCl
3141
throw new InvalidOperationException($"Unsupported blob format version: {version}");
3242
}
3343

34-
var contentType = metadata.TryGetValue("ContentType", out var ct) ? ct : "application/octet-stream";
44+
var contentType = metadata.TryGetValue("ContentType", out var ct) ? Uri.UnescapeDataString(ct) : "application/octet-stream";
3545
var bodySize = metadata.TryGetValue("BodySize", out var sizeStr) && int.TryParse(sizeStr, out var size) ? size : 0;
3646
var isCompressed = metadata.TryGetValue("IsCompressed", out var compressedStr) && bool.TryParse(compressedStr, out var compressed) && compressed;
3747
var etag = properties.Details.ETag.ToString();
@@ -101,15 +111,14 @@ public async Task WriteBodyAsync(string bodyId, ReadOnlyMemory<byte> body, strin
101111

102112
var options = new BlobUploadOptions
103113
{
104-
AccessTier = AccessTier.Cool,
105114
TransferValidation = new UploadTransferValidationOptions
106115
{
107116
ChecksumAlgorithm = StorageChecksumAlgorithm.Auto
108117
},
109118
Metadata = new Dictionary<string, string>
110119
{
111120
{ "FormatVersion", FormatVersion },
112-
{ "ContentType", contentType },
121+
{ "ContentType", Uri.EscapeDataString(contentType) },
113122
{ "BodySize", body.Length.ToString() },
114123
{ "IsCompressed", shouldCompress.ToString() }
115124
}

src/ServiceControl.Audit.Persistence.Sql.PostgreSQL/PostgreSqlAuditPersistenceConfiguration.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
namespace ServiceControl.Audit.Persistence.Sql.PostgreSQL;
22

3-
using Configuration;
4-
53
public class PostgreSqlAuditPersistenceConfiguration : IPersistenceConfiguration
64
{
75
const string DatabaseConnectionStringKey = "Database/ConnectionString";
86
const string CommandTimeoutKey = "Database/CommandTimeout";
97
const string MessageBodyStoragePathKey = "MessageBody/StoragePath";
108
const string MinBodySizeForCompressionKey = "MessageBody/MinCompressionSize";
119
const string StoreMessageBodiesOnDiskKey = "MessageBody/StoreOnDisk";
10+
const string MessageBodyStorageConnectionStringKey = "MessageBody/StorageConnectionString";
1211

1312
public string Name => "PostgreSQL";
1413

@@ -18,7 +17,8 @@ public class PostgreSqlAuditPersistenceConfiguration : IPersistenceConfiguration
1817
CommandTimeoutKey,
1918
MessageBodyStoragePathKey,
2019
MinBodySizeForCompressionKey,
21-
StoreMessageBodiesOnDiskKey
20+
StoreMessageBodiesOnDiskKey,
21+
MessageBodyStorageConnectionStringKey
2222
];
2323

2424
public IPersistence Create(PersistenceSettings settings)
@@ -27,7 +27,7 @@ public IPersistence Create(PersistenceSettings settings)
2727

2828
// Initialize message body storage path
2929
var messageBodyStoragePath = GetSetting(settings, MessageBodyStoragePathKey, string.Empty);
30-
var messageBodyStorageConnectionString = GetSetting(settings, "MessageBody/StorageConnectionString", string.Empty);
30+
var messageBodyStorageConnectionString = GetSetting(settings, MessageBodyStorageConnectionStringKey, string.Empty);
3131

3232
var specificSettings = new PostgreSqlAuditPersisterSettings(
3333
settings.AuditRetentionPeriod,

src/ServiceControl.Audit.Persistence.Sql.SqlServer/SqlServerAuditPersistenceConfiguration.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class SqlServerAuditPersistenceConfiguration : IPersistenceConfiguration
77
const string MessageBodyStoragePathKey = "MessageBody/StoragePath";
88
const string MinBodySizeForCompressionKey = "MessageBody/MinCompressionSize";
99
const string StoreMessageBodiesOnDiskKey = "MessageBody/StoreOnDisk";
10-
10+
const string MessageBodyStorageConnectionStringKey = "MessageBody/StorageConnectionString";
1111
public string Name => "SqlServer";
1212

1313
public IEnumerable<string> ConfigurationKeys =>
@@ -16,7 +16,8 @@ public class SqlServerAuditPersistenceConfiguration : IPersistenceConfiguration
1616
CommandTimeoutKey,
1717
MessageBodyStoragePathKey,
1818
MinBodySizeForCompressionKey,
19-
StoreMessageBodiesOnDiskKey
19+
StoreMessageBodiesOnDiskKey,
20+
MessageBodyStorageConnectionStringKey
2021
];
2122

2223
public IPersistence Create(PersistenceSettings settings)
@@ -25,7 +26,7 @@ public IPersistence Create(PersistenceSettings settings)
2526

2627
// Initialize message body storage path
2728
var messageBodyStoragePath = GetSetting(settings, MessageBodyStoragePathKey, string.Empty);
28-
var messageBodyStorageConnectionString = GetSetting(settings, "MessageBody/StorageConnectionString", string.Empty);
29+
var messageBodyStorageConnectionString = GetSetting(settings, MessageBodyStorageConnectionStringKey, string.Empty);
2930

3031
var specificSettings = new SqlServerAuditPersisterSettings(
3132
settings.AuditRetentionPeriod,

0 commit comments

Comments
 (0)