From a8c746f7cbb41a50ab400fb97c796e63f938a8b9 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Thu, 12 Jun 2025 15:43:12 +0800 Subject: [PATCH 01/27] convert SC transports from NServiceBus.Logging to Microsoft.Extensions.Logging --- .../DeadLetterQueueCheck.cs | 17 +++++----- .../QueueLengthProvider.cs | 16 +++++----- .../QueueLengthProvider.cs | 19 ++++++----- .../QueueLengthProvider.cs | 15 +++++---- .../DeadLetterQueueCheck.cs | 32 ++++++++----------- .../TransportTestsConfiguration.cs | 3 +- .../PostgreSqlTransportCustomization.cs | 8 ++--- .../QueueLengthProvider.cs | 11 ++++--- .../QueueLengthProvider.cs | 12 ++++--- .../TransportTestsConfiguration.cs | 3 +- .../QueueLengthProvider.cs | 20 ++++++------ .../SQSTransportCustomization.cs | 10 +++--- .../TransportTestsConfiguration.cs | 3 +- .../QueueLengthProvider.cs | 11 ++++--- .../SqlServerTransportCustomization.cs | 8 ++--- .../ServiceControl.Transports.csproj | 1 + .../TransportManifest.cs | 11 ++++--- 17 files changed, 102 insertions(+), 98 deletions(-) diff --git a/src/ServiceControl.Transports.ASBS/DeadLetterQueueCheck.cs b/src/ServiceControl.Transports.ASBS/DeadLetterQueueCheck.cs index abcc4fd05c..e44be27ca8 100644 --- a/src/ServiceControl.Transports.ASBS/DeadLetterQueueCheck.cs +++ b/src/ServiceControl.Transports.ASBS/DeadLetterQueueCheck.cs @@ -4,14 +4,15 @@ using System.Threading; using System.Threading.Tasks; using Azure.Messaging.ServiceBus.Administration; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; + using ServiceControl.Infrastructure; public class DeadLetterQueueCheck : CustomCheck { public DeadLetterQueueCheck(TransportSettings settings) : base(id: "Dead Letter Queue", category: "Transport", repeatAfter: TimeSpan.FromHours(1)) { - Logger.Debug("Azure Service Bus Dead Letter Queue custom check starting"); + Logger.LogDebug("Azure Service Bus Dead Letter Queue custom check starting"); connectionString = settings.ConnectionString; stagingQueue = $"{settings.EndpointName}.staging"; @@ -25,7 +26,7 @@ public override async Task PerformCheck(CancellationToken cancellat return CheckResult.Pass; } - Logger.Debug("Checking Dead Letter Queue length"); + Logger.LogDebug("Checking Dead Letter Queue length"); var managementClient = new ServiceBusAdministrationClient(connectionString); var queueRuntimeInfo = await managementClient.GetQueueRuntimePropertiesAsync(stagingQueue, cancellationToken); @@ -33,13 +34,11 @@ public override async Task PerformCheck(CancellationToken cancellat if (deadLetterMessageCount > 0) { - var result = $"{deadLetterMessageCount} messages in the Dead Letter Queue '{stagingQueue}'. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages."; - - Logger.Warn(result); - return CheckResult.Failed(result); + Logger.LogWarning("{DeadLetterMessageCount} messages in the Dead Letter Queue '{StagingQueue}'. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages.", deadLetterMessageCount, stagingQueue); + return CheckResult.Failed($"{deadLetterMessageCount} messages in the Dead Letter Queue '{stagingQueue}'. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages."); } - Logger.Debug("No messages in Dead Letter Queue"); + Logger.LogDebug("No messages in Dead Letter Queue"); return CheckResult.Pass; } @@ -49,6 +48,6 @@ public override async Task PerformCheck(CancellationToken cancellat bool runCheck; - static readonly ILog Logger = LogManager.GetLogger(typeof(DeadLetterQueueCheck)); + static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(typeof(DeadLetterQueueCheck)); } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs b/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs index 24021da49a..f6fb44e593 100644 --- a/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs @@ -6,17 +6,18 @@ namespace ServiceControl.Transports.ASBS using System.Threading; using System.Threading.Tasks; using Azure.Messaging.ServiceBus.Administration; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) : base(settings, store) + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) : base(settings, store) { var connectionSettings = ConnectionStringParser.Parse(ConnectionString); queryDelayInterval = connectionSettings.QueryDelayInterval ?? TimeSpan.FromMilliseconds(500); managementClient = connectionSettings.AuthenticationMethod.BuildManagementClient(); + this.logger = logger; } public override void TrackEndpointInputQueue(EndpointToQueueMapping queueToTrack) => @@ -32,14 +33,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { try { - Logger.Debug("Waiting for next interval"); + logger.LogDebug("Waiting for next interval"); await Task.Delay(queryDelayInterval, stoppingToken); - Logger.DebugFormat("Querying management client."); + logger.LogDebug("Querying management client."); var queueRuntimeInfos = await GetQueueList(stoppingToken); - Logger.DebugFormat("Retrieved details of {0} queues", queueRuntimeInfos.Count); + logger.LogDebug("Retrieved details of {QueueCount} queues", queueRuntimeInfos.Count); UpdateAllQueueLengths(queueRuntimeInfos); } @@ -49,7 +50,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception e) { - Logger.Error("Error querying Azure Service Bus queue sizes.", e); + logger.LogError(e, "Error querying Azure Service Bus queue sizes."); } } } @@ -109,7 +110,6 @@ void UpdateQueueLength(KeyValuePair monitoredEndpoint, IReadOnly readonly ConcurrentDictionary endpointQueueMappings = new ConcurrentDictionary(); readonly ServiceBusAdministrationClient managementClient; readonly TimeSpan queryDelayInterval; - - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs b/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs index 58a7b5783d..48ebcf6a6d 100644 --- a/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs @@ -1,19 +1,22 @@ namespace ServiceControl.Transports.ASQ { using System; - using System.Linq; - using System.Threading.Tasks; using System.Collections.Concurrent; + using System.Linq; using System.Threading; - using NServiceBus.Logging; + using System.Threading.Tasks; using Azure.Storage.Queues; using Azure.Storage.Queues.Models; + using Microsoft.Extensions.Logging; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) : base(settings, store) - => connectionString = ConnectionString.RemoveCustomConnectionStringParts(out _); + { + connectionString = ConnectionString.RemoveCustomConnectionStringParts(out _); + this.logger = logger; + } public override void TrackEndpointInputQueue(EndpointToQueueMapping queueToTrack) { @@ -48,7 +51,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception e) { - Logger.Error("Error querying sql queue sizes.", e); + logger.LogError(e, "Error querying sql queue sizes."); } } } @@ -76,7 +79,7 @@ async Task FetchLength(QueueLengthValue queueLength, CancellationToken cancellat // simple "log once" approach to do not flood logs if (problematicQueuesNames.TryAdd(queueLength.QueueName, queueLength.QueueName)) { - Logger.Error($"Obtaining Azure Storage Queue count failed for '{queueLength.QueueName}'", ex); + logger.LogError(ex, "Obtaining Azure Storage Queue count failed for '{QueueName}'", queueLength.QueueName); } } } @@ -102,7 +105,7 @@ void UpdateQueueLengthStore() readonly ConcurrentDictionary queueLengths = new ConcurrentDictionary(); readonly ConcurrentDictionary problematicQueuesNames = new ConcurrentDictionary(); - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; static readonly TimeSpan QueryDelayInterval = TimeSpan.FromMilliseconds(200); class QueueLengthValue diff --git a/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs b/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs index 68959ada38..93bc2fcc41 100644 --- a/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs @@ -7,14 +7,17 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using ServiceControl.Transports.Learning; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) - : base(settings, store) => + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) + : base(settings, store) + { rootFolder = LearningTransportCustomization.FindStoragePath(ConnectionString); + this.logger = logger; + } public override void TrackEndpointInputQueue(EndpointToQueueMapping queueToTrack) => endpointsHash.AddOrUpdate(queueToTrack, queueToTrack, (_, __) => queueToTrack); @@ -36,7 +39,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception ex) { - Log.Warn("Problem getting learning transport queue length", ex); + logger.LogWarning(ex, "Problem getting learning transport queue length"); } } } @@ -60,7 +63,7 @@ void UpdateStore(ILookup queueLengths) } else { - Log.Warn($"Queue Length data missing for queue {instance.InputQueue} (Endpoint {instance.EndpointName})"); + logger.LogWarning("Queue Length data missing for queue {InputQueue} (Endpoint {EndpointName})", instance.InputQueue, instance.EndpointName); } } } @@ -87,7 +90,7 @@ void UpdateStore(ILookup queueLengths) readonly ConcurrentDictionary endpointsHash = new ConcurrentDictionary(); static readonly TimeSpan QueryDelayInterval = TimeSpan.FromMilliseconds(200); - static readonly ILog Log = LogManager.GetLogger(); + readonly ILogger logger; } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.Msmq/DeadLetterQueueCheck.cs b/src/ServiceControl.Transports.Msmq/DeadLetterQueueCheck.cs index 7f229048f6..61c5378d4d 100644 --- a/src/ServiceControl.Transports.Msmq/DeadLetterQueueCheck.cs +++ b/src/ServiceControl.Transports.Msmq/DeadLetterQueueCheck.cs @@ -5,13 +5,13 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using Transports; public class DeadLetterQueueCheck : CustomCheck { - public DeadLetterQueueCheck(TransportSettings settings) : + public DeadLetterQueueCheck(TransportSettings settings, ILogger logger) : base("Dead Letter Queue", "Transport", TimeSpan.FromHours(1)) { runCheck = settings.RunCustomChecks; @@ -20,7 +20,7 @@ public DeadLetterQueueCheck(TransportSettings settings) : return; } - Logger.Debug("MSMQ Dead Letter Queue custom check starting"); + logger.LogDebug("MSMQ Dead Letter Queue custom check starting"); categoryName = Read("Msmq/PerformanceCounterCategoryName", "MSMQ Queue"); counterName = Read("Msmq/PerformanceCounterName", "Messages in Queue"); @@ -32,8 +32,10 @@ public DeadLetterQueueCheck(TransportSettings settings) : } catch (InvalidOperationException ex) { - Logger.Error(CounterMightBeLocalized(categoryName, counterName, counterInstanceName), ex); + logger.LogError(ex, CounterMightBeLocalized("CategoryName", "CounterName", "CounterInstanceName"), categoryName, counterName, counterInstanceName); } + + this.logger = logger; } public override Task PerformCheck(CancellationToken cancellationToken = default) @@ -43,9 +45,8 @@ public override Task PerformCheck(CancellationToken cancellationTok return CheckResult.Pass; } - Logger.Debug("Checking Dead Letter Queue length"); + logger.LogDebug("Checking Dead Letter Queue length"); float currentValue; - string result; try { if (dlqPerformanceCounter == null) @@ -57,25 +58,18 @@ public override Task PerformCheck(CancellationToken cancellationTok } catch (InvalidOperationException ex) { - result = CounterMightBeLocalized(categoryName, counterName, counterInstanceName); - Logger.Warn(result, ex); - return CheckResult.Failed(result); + logger.LogWarning(ex, CounterMightBeLocalized("CategoryName", "CounterName", "CounterInstanceName"), categoryName, counterName, counterInstanceName); + return CheckResult.Failed(CounterMightBeLocalized(categoryName, counterName, counterInstanceName)); } if (currentValue <= 0) { - Logger.Debug("No messages in Dead Letter Queue"); + logger.LogDebug("No messages in Dead Letter Queue"); return CheckResult.Pass; } - result = MessagesInDeadLetterQueue(currentValue); - Logger.Warn(result); - return CheckResult.Failed(result); - } - - static string MessagesInDeadLetterQueue(float currentValue) - { - return $"{currentValue} messages in the Dead Letter Queue on {Environment.MachineName}. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages."; + logger.LogWarning("{DeadLetterMessageCount} messages in the Dead Letter Queue on {MachineName}. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages.", currentValue, Environment.MachineName); + return CheckResult.Failed($"{currentValue} messages in the Dead Letter Queue on {Environment.MachineName}. This could indicate a problem with ServiceControl's retries. Please submit a support ticket to Particular if you would like help from our engineers to ensure no message loss while resolving these dead letter messages."); } static string CounterMightBeLocalized(string categoryName, string counterName, string counterInstanceName) @@ -123,6 +117,6 @@ static bool TryRead(string root, string name, out string value) string counterInstanceName; bool runCheck; - static readonly ILog Logger = LogManager.GetLogger(typeof(DeadLetterQueueCheck)); + readonly ILogger logger; } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs index 819248c612..2d6c34b86c 100644 --- a/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs @@ -2,6 +2,7 @@ { using System; using System.Threading.Tasks; + using ServiceControl.Infrastructure; using ServiceControl.Transports.PostgreSql; using Transports; @@ -13,7 +14,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new PostgreSqlTransportCustomization(); + TransportCustomization = new PostgreSqlTransportCustomization(LoggerUtil.CreateStaticLogger()); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs b/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs index 934bee47a1..c5f878f21f 100644 --- a/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs +++ b/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs @@ -4,11 +4,11 @@ using System.Runtime.CompilerServices; using BrokerThroughput; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using NServiceBus; -using NServiceBus.Logging; using NServiceBus.Transport.PostgreSql; -public class PostgreSqlTransportCustomization : TransportCustomization +public class PostgreSqlTransportCustomization(ILogger logger) : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, PostgreSqlTransport transportDefinition, TransportSettings transportSettings) { @@ -66,7 +66,7 @@ protected override PostgreSqlTransport CreateTransport(TransportSettings transpo if (transportSettings.GetOrDefault("TransportSettings.EnableDtc")) { - Logger.Error("The EnableDtc setting is no longer supported natively within ServiceControl. If you require distributed transactions, you will have to use a Transport Adapter (https://docs.particular.net/servicecontrol/transport-adapter/)"); + logger.LogError("The EnableDtc setting is no longer supported natively within ServiceControl. If you require distributed transactions, you will have to use a Transport Adapter (https://docs.particular.net/servicecontrol/transport-adapter/)"); } DisableDelayedDelivery(transport) = true; @@ -93,6 +93,4 @@ protected override string ToTransportQualifiedQueueNameCore(string queueName) static extern ref bool DisableDelayedDelivery(PostgreSqlTransport transport); const string DefaultSubscriptionTableName = "SubscriptionRouting"; - - static readonly ILog Logger = LogManager.GetLogger(typeof(PostgreSqlTransportCustomization)); } \ No newline at end of file diff --git a/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs b/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs index d58b5c526c..79b128032d 100644 --- a/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs @@ -6,17 +6,18 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Npgsql; -using NServiceBus.Logging; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) : base(settings, store) + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) : base(settings, store) { connectionString = ConnectionString .RemoveCustomConnectionStringParts(out var customSchema, out _); defaultSchema = customSchema ?? "public"; + this.logger = logger; } public override void TrackEndpointInputQueue(EndpointToQueueMapping queueToTrack) { @@ -55,7 +56,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception e) { - Logger.Error("Error querying sql queue sizes.", e); + logger.LogError(e, "Error querying SQL queue sizes."); } } } @@ -113,7 +114,7 @@ async Task UpdateChunk(NpgsqlConnection connection, KeyValuePair(); + readonly ILogger logger; static readonly TimeSpan QueryDelayInterval = TimeSpan.FromMilliseconds(200); diff --git a/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs b/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs index 3c60019abe..311a408aa9 100644 --- a/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs @@ -4,12 +4,12 @@ using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using NServiceBus.Transport.RabbitMQ.ManagementApi; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store, ITransportCustomization transportCustomization) : base(settings, store) + public QueueLengthProvider(TransportSettings settings, Action store, ITransportCustomization transportCustomization, ILogger logger) : base(settings, store) { if (transportCustomization is IManagementClientProvider provider) { @@ -19,6 +19,8 @@ public QueueLengthProvider(TransportSettings settings, Action @@ -50,7 +52,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception e) { - Logger.Error("Queue length query loop failure.", e); + logger.LogError(e, "Queue length query loop failure."); } } } @@ -91,7 +93,7 @@ async Task FetchQueueLengths(CancellationToken cancellationToken) } catch (Exception e) { - Logger.Warn($"Error querying queue length for {queueName}", e); + logger.LogWarning(e, "Error querying queue length for {QueueName}", queueName); } } } @@ -101,7 +103,7 @@ async Task FetchQueueLengths(CancellationToken cancellationToken) readonly ConcurrentDictionary endpointQueues = new(); readonly ConcurrentDictionary sizes = new(); - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; readonly Lazy managementClient; } diff --git a/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs index c64f5d1bca..c931ef2f58 100644 --- a/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs @@ -2,6 +2,7 @@ { using System; using System.Threading.Tasks; + using ServiceControl.Infrastructure; using Transports; using Transports.SQS; @@ -13,7 +14,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new SQSTransportCustomization(); + TransportCustomization = new SQSTransportCustomization(LoggerUtil.CreateStaticLogger()); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs b/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs index 431d5358ac..ea8901fca9 100644 --- a/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs @@ -1,19 +1,19 @@ namespace ServiceControl.Transports.SQS { using System; - using System.Linq; - using System.Threading.Tasks; - using System.Data.Common; using System.Collections.Concurrent; using System.Collections.Generic; + using System.Data.Common; + using System.Linq; using System.Threading; + using System.Threading.Tasks; using Amazon.Runtime; using Amazon.SQS; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) : base(settings, store) + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) : base(settings, store) { var builder = new DbConnectionStringBuilder { ConnectionString = ConnectionString }; if (builder.ContainsKey("AccessKeyId") || builder.ContainsKey("SecretAccessKey")) @@ -24,13 +24,15 @@ public QueueLengthProvider(TransportSettings settings, Action clientFactory = () => new AmazonSQSClient(); - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; } } diff --git a/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs b/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs index 8c17902b53..4ae8e6a82e 100644 --- a/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs +++ b/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs @@ -2,7 +2,6 @@ { using System; using System.Linq; - using System.Runtime.CompilerServices; using Amazon; using Amazon.Runtime; using Amazon.S3; @@ -10,11 +9,11 @@ using Amazon.SQS; using BrokerThroughput; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Configuration.AdvancedExtensibility; - using NServiceBus.Logging; - public class SQSTransportCustomization : TransportCustomization + public class SQSTransportCustomization(ILogger logger) : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, SqsTransport transportDefinition, TransportSettings transportSettings) { @@ -65,7 +64,7 @@ protected override SqsTransport CreateTransport(TransportSettings transportSetti else { //See https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html#creds-assign - log.Info( + logger.LogInformation( "BasicAWSCredentials have not been supplied in the connection string. Attempting to use existing environment or IAM role credentials for SQS Client."); sqsClient = new AmazonSQSClient(); snsClient = new AmazonSimpleNotificationServiceClient(); @@ -101,7 +100,7 @@ protected override SqsTransport CreateTransport(TransportSettings transportSetti } else { - log.Info( + logger.LogInformation( "BasicAWSCredentials have not been supplied in the connection string. Attempting to use existing environment or IAM role credentials for S3 Client."); s3Client = new AmazonS3Client(); } @@ -121,6 +120,5 @@ static void PromoteEnvironmentVariableFromConnectionString(string value, string environmentVariableName) => Environment.SetEnvironmentVariable(environmentVariableName, value, EnvironmentVariableTarget.Process); - static readonly ILog log = LogManager.GetLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs index 9cf82c6dde..abcad12793 100644 --- a/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs @@ -2,6 +2,7 @@ { using System; using System.Threading.Tasks; + using ServiceControl.Infrastructure; using Transports; using Transports.SqlServer; @@ -13,7 +14,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new SqlServerTransportCustomization(); + TransportCustomization = new SqlServerTransportCustomization(LoggerUtil.CreateStaticLogger()); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs b/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs index 196905a678..b9fe29a227 100644 --- a/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs @@ -7,16 +7,17 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Data.SqlClient; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; class QueueLengthProvider : AbstractQueueLengthProvider { - public QueueLengthProvider(TransportSettings settings, Action store) : base(settings, store) + public QueueLengthProvider(TransportSettings settings, Action store, ILogger logger) : base(settings, store) { connectionString = ConnectionString .RemoveCustomConnectionStringParts(out var customSchema, out _); defaultSchema = customSchema ?? "dbo"; + this.logger = logger; } public override void TrackEndpointInputQueue(EndpointToQueueMapping queueToTrack) { @@ -53,7 +54,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } catch (Exception e) { - Logger.Error("Error querying sql queue sizes.", e); + logger.LogError(e, "Error querying sql queue sizes."); } } } @@ -111,7 +112,7 @@ async Task UpdateChunk(SqlConnection connection, KeyValuePair[] c if (queueLength == -1) { - Logger.Warn($"Table {chunkPair.Key} does not exist."); + logger.LogWarning("Table {TableName} does not exist.", chunkPair.Key); } else { @@ -128,7 +129,7 @@ async Task UpdateChunk(SqlConnection connection, KeyValuePair[] c readonly string connectionString; readonly string defaultSchema; - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; static readonly TimeSpan QueryDelayInterval = TimeSpan.FromMilliseconds(200); diff --git a/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs b/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs index 24d3dec0f3..a89ee8fecc 100644 --- a/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs +++ b/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs @@ -4,12 +4,12 @@ using System.Runtime.CompilerServices; using BrokerThroughput; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Configuration.AdvancedExtensibility; - using NServiceBus.Logging; using NServiceBus.Transport.SqlServer; - public class SqlServerTransportCustomization : TransportCustomization + public class SqlServerTransportCustomization(ILogger logger) : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, SqlServerTransport transportDefinition, TransportSettings transportSettings) { @@ -73,7 +73,7 @@ protected override SqlServerTransport CreateTransport(TransportSettings transpor if (transportSettings.GetOrDefault("TransportSettings.EnableDtc")) { - Logger.Error("The EnableDtc setting is no longer supported natively within ServiceControl. If you require distributed transactions, you will have to use a Transport Adapter (https://docs.particular.net/servicecontrol/transport-adapter/)"); + logger.LogError("The EnableDtc setting is no longer supported natively within ServiceControl. If you require distributed transactions, you will have to use a Transport Adapter (https://docs.particular.net/servicecontrol/transport-adapter/)"); } DisableDelayedDelivery(transport) = true; @@ -87,7 +87,5 @@ protected override SqlServerTransport CreateTransport(TransportSettings transpor static extern ref bool DisableDelayedDelivery(SqlServerTransport transport); const string defaultSubscriptionTableName = "SubscriptionRouting"; - - static readonly ILog Logger = LogManager.GetLogger(typeof(SqlServerTransportCustomization)); } } \ No newline at end of file diff --git a/src/ServiceControl.Transports/ServiceControl.Transports.csproj b/src/ServiceControl.Transports/ServiceControl.Transports.csproj index 435491c160..263429e5d4 100644 --- a/src/ServiceControl.Transports/ServiceControl.Transports.csproj +++ b/src/ServiceControl.Transports/ServiceControl.Transports.csproj @@ -9,6 +9,7 @@ + diff --git a/src/ServiceControl.Transports/TransportManifest.cs b/src/ServiceControl.Transports/TransportManifest.cs index c37538867a..429d80db9b 100644 --- a/src/ServiceControl.Transports/TransportManifest.cs +++ b/src/ServiceControl.Transports/TransportManifest.cs @@ -5,7 +5,8 @@ using System.IO; using System.Linq; using System.Text.Json; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; + using ServiceControl.Infrastructure; public class TransportManifest { @@ -60,7 +61,7 @@ static TransportManifestLibrary() } catch (Exception ex) { - logger.Warn($"Failed to load transport manifests from {assemblyDirectory}", ex); + logger.LogWarning(ex, "Failed to load transport manifests from {AssemblyDirectory}", assemblyDirectory); } try @@ -79,10 +80,10 @@ static TransportManifestLibrary() } catch (Exception ex) { - logger.Warn($"Failed to load transport manifests from development locations", ex); + logger.LogWarning(ex, "Failed to load transport manifests from development locations"); } - TransportManifests.SelectMany(t => t.Definitions).ToList().ForEach(m => logger.Info($"Found transport manifest for {m.DisplayName}")); + TransportManifests.SelectMany(t => t.Definitions).ToList().ForEach(m => logger.LogInformation("Found transport manifest for {TransportManifestDisplayName}", m.DisplayName)); } static string GetAssemblyDirectory() @@ -105,7 +106,7 @@ public static TransportManifestDefinition Find(string transportType) return transportManifestDefinition; } - static readonly ILog logger = LogManager.GetLogger(typeof(TransportManifestLibrary)); + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(typeof(TransportManifestLibrary)); } } From 42d01e7d03328ebdfa00a8ccc050bbd485a29147 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Mon, 16 Jun 2025 07:20:35 +0800 Subject: [PATCH 02/27] remove signedassembly requirement so that infrastructure can be imported --- src/ServiceControl.Transports/ServiceControl.Transports.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ServiceControl.Transports/ServiceControl.Transports.csproj b/src/ServiceControl.Transports/ServiceControl.Transports.csproj index 263429e5d4..263249e023 100644 --- a/src/ServiceControl.Transports/ServiceControl.Transports.csproj +++ b/src/ServiceControl.Transports/ServiceControl.Transports.csproj @@ -2,7 +2,6 @@ net8.0 - true ..\NServiceBus.snk From 96ec1242a80d3658cc1c788440dcb398fae22f7d Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Mon, 16 Jun 2025 07:39:31 +0800 Subject: [PATCH 03/27] revert previous change and instead propogate signing back to servicecontrol.infrastructure --- .../ServiceControl.Configuration.csproj | 2 ++ .../ServiceControl.Infrastructure.csproj | 2 ++ src/ServiceControl.Transports/ServiceControl.Transports.csproj | 1 + 3 files changed, 5 insertions(+) diff --git a/src/ServiceControl.Configuration/ServiceControl.Configuration.csproj b/src/ServiceControl.Configuration/ServiceControl.Configuration.csproj index 2a585451b7..302ef7cbea 100644 --- a/src/ServiceControl.Configuration/ServiceControl.Configuration.csproj +++ b/src/ServiceControl.Configuration/ServiceControl.Configuration.csproj @@ -2,6 +2,8 @@ net8.0 + true + ..\NServiceBus.snk diff --git a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj index 123180a850..a686479039 100644 --- a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj +++ b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj @@ -2,6 +2,8 @@ net8.0 + true + ..\NServiceBus.snk diff --git a/src/ServiceControl.Transports/ServiceControl.Transports.csproj b/src/ServiceControl.Transports/ServiceControl.Transports.csproj index 263249e023..263429e5d4 100644 --- a/src/ServiceControl.Transports/ServiceControl.Transports.csproj +++ b/src/ServiceControl.Transports/ServiceControl.Transports.csproj @@ -2,6 +2,7 @@ net8.0 + true ..\NServiceBus.snk From 5aaabe6af15a776920f5ec7ab0406ab28a7827b7 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Mon, 16 Jun 2025 08:13:00 +0800 Subject: [PATCH 04/27] fix signature of customisation classes that are dynamically created --- .../PostgreSqlTransportCustomization.cs | 5 ++++- .../SQSTransportCustomization.cs | 5 ++++- .../SqlServerTransportCustomization.cs | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs b/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs index c5f878f21f..4523792f18 100644 --- a/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs +++ b/src/ServiceControl.Transports.PostgreSql/PostgreSqlTransportCustomization.cs @@ -7,8 +7,9 @@ using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Transport.PostgreSql; +using ServiceControl.Infrastructure; -public class PostgreSqlTransportCustomization(ILogger logger) : TransportCustomization +public class PostgreSqlTransportCustomization() : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, PostgreSqlTransport transportDefinition, TransportSettings transportSettings) { @@ -93,4 +94,6 @@ protected override string ToTransportQualifiedQueueNameCore(string queueName) static extern ref bool DisableDelayedDelivery(PostgreSqlTransport transport); const string DefaultSubscriptionTableName = "SubscriptionRouting"; + + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(); } \ No newline at end of file diff --git a/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs b/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs index 4ae8e6a82e..8aa9a0d530 100644 --- a/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs +++ b/src/ServiceControl.Transports.SQS/SQSTransportCustomization.cs @@ -12,8 +12,9 @@ using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Configuration.AdvancedExtensibility; + using ServiceControl.Infrastructure; - public class SQSTransportCustomization(ILogger logger) : TransportCustomization + public class SQSTransportCustomization() : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, SqsTransport transportDefinition, TransportSettings transportSettings) { @@ -120,5 +121,7 @@ static void PromoteEnvironmentVariableFromConnectionString(string value, string environmentVariableName) => Environment.SetEnvironmentVariable(environmentVariableName, value, EnvironmentVariableTarget.Process); + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(); + } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs b/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs index a89ee8fecc..034a23dc9c 100644 --- a/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs +++ b/src/ServiceControl.Transports.SqlServer/SqlServerTransportCustomization.cs @@ -8,8 +8,9 @@ using NServiceBus; using NServiceBus.Configuration.AdvancedExtensibility; using NServiceBus.Transport.SqlServer; + using ServiceControl.Infrastructure; - public class SqlServerTransportCustomization(ILogger logger) : TransportCustomization + public class SqlServerTransportCustomization() : TransportCustomization { protected override void CustomizeTransportForPrimaryEndpoint(EndpointConfiguration endpointConfiguration, SqlServerTransport transportDefinition, TransportSettings transportSettings) { @@ -87,5 +88,7 @@ protected override SqlServerTransport CreateTransport(TransportSettings transpor static extern ref bool DisableDelayedDelivery(SqlServerTransport transport); const string defaultSubscriptionTableName = "SubscriptionRouting"; + + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(); } } \ No newline at end of file From 67920ff323507faca9b36f50018aefded54ed10a Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Mon, 16 Jun 2025 08:49:17 +0800 Subject: [PATCH 05/27] add ilogger to test services and remove direct construction with logger --- .../TransportTestsConfiguration.cs | 3 +-- .../TransportTestsConfiguration.cs | 3 +-- .../TransportTestsConfiguration.cs | 3 +-- src/ServiceControl.Transports.Tests/TransportTestFixture.cs | 2 ++ 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs index 2d6c34b86c..819248c612 100644 --- a/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.PostgreSql.Tests/TransportTestsConfiguration.cs @@ -2,7 +2,6 @@ { using System; using System.Threading.Tasks; - using ServiceControl.Infrastructure; using ServiceControl.Transports.PostgreSql; using Transports; @@ -14,7 +13,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new PostgreSqlTransportCustomization(LoggerUtil.CreateStaticLogger()); + TransportCustomization = new PostgreSqlTransportCustomization(); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs index c931ef2f58..c64f5d1bca 100644 --- a/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.SQS.Tests/TransportTestsConfiguration.cs @@ -2,7 +2,6 @@ { using System; using System.Threading.Tasks; - using ServiceControl.Infrastructure; using Transports; using Transports.SQS; @@ -14,7 +13,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new SQSTransportCustomization(LoggerUtil.CreateStaticLogger()); + TransportCustomization = new SQSTransportCustomization(); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs index abcad12793..9cf82c6dde 100644 --- a/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs +++ b/src/ServiceControl.Transports.SqlServer.Tests/TransportTestsConfiguration.cs @@ -2,7 +2,6 @@ { using System; using System.Threading.Tasks; - using ServiceControl.Infrastructure; using Transports; using Transports.SqlServer; @@ -14,7 +13,7 @@ partial class TransportTestsConfiguration public Task Configure() { - TransportCustomization = new SqlServerTransportCustomization(LoggerUtil.CreateStaticLogger()); + TransportCustomization = new SqlServerTransportCustomization(); ConnectionString = Environment.GetEnvironmentVariable(ConnectionStringKey); if (string.IsNullOrEmpty(ConnectionString)) diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index 0f6d9027e1..cd8c301137 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -20,6 +20,7 @@ class TransportTestFixture [SetUp] public virtual async Task Setup() { + //TODO remove LogManager usage LogManager.UseFactory(new TestContextAppenderFactory()); configuration = new TransportTestsConfiguration(); testCancellationTokenSource = Debugger.IsAttached ? new CancellationTokenSource() : new CancellationTokenSource(TestTimeout); @@ -102,6 +103,7 @@ protected async Task StartQueueLengthProvider(string queueName configuration.TransportCustomization.CustomizeMonitoringEndpoint(new EndpointConfiguration("queueName"), transportSettings); serviceCollection.AddSingleton>((qlt, _) => onQueueLengthReported(qlt.First())); + serviceCollection.AddLogging(); var serviceProvider = serviceCollection.BuildServiceProvider(); queueLengthProvider = serviceProvider.GetRequiredService(); From b3c690a6c198c3976157c4b48351ce76e69157a4 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Tue, 17 Jun 2025 07:48:10 +0800 Subject: [PATCH 06/27] get tests to use ilogger --- .../LoggerUtil.cs | 14 ++- .../FullEndpointTestFixture.cs | 2 + .../TestContextAppender.cs | 86 +++---------------- .../TestContextAppenderFactory.cs | 13 ++- .../TransportManifestLibraryTests.cs | 7 ++ .../TransportTestFixture.cs | 3 +- 6 files changed, 46 insertions(+), 79 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 039d0b4938..0757d17fa0 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -6,8 +6,18 @@ public static class LoggerUtil { + /// + /// used for tests + /// + public static ILoggerFactory LoggerFactory { private get; set; } + public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) { + if (LoggerFactory != null) + { + return; + } + //TODO: can we get these from settings too? loggingBuilder.AddNLog(); loggingBuilder.AddSeq(); @@ -16,13 +26,13 @@ public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel lev public static ILogger CreateStaticLogger(LogLevel level = LogLevel.Information) { - var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); + var factory = LoggerFactory ?? Microsoft.Extensions.Logging.LoggerFactory.Create(configure => configure.BuildLogger(level)); return factory.CreateLogger(); } public static ILogger CreateStaticLogger(Type type, LogLevel level = LogLevel.Information) { - var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); + var factory = LoggerFactory ?? Microsoft.Extensions.Logging.LoggerFactory.Create(configure => configure.BuildLogger(level)); return factory.CreateLogger(type); } } diff --git a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs index 55f7f24383..f2c4d13313 100644 --- a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using NServiceBus.AcceptanceTesting.Customization; using NUnit.Framework; + using ServiceControl.Infrastructure; [TestFixture] class FullEndpointTestFixture @@ -11,6 +12,7 @@ class FullEndpointTestFixture [SetUp] public virtual async Task Setup() { + LoggerUtil.LoggerFactory = new TestContextAppenderFactory(); configuration = new TransportTestsConfiguration(); var queueSuffix = $"-{System.IO.Path.GetRandomFileName().Replace(".", string.Empty)}"; diff --git a/src/ServiceControl.Transports.Tests/TestContextAppender.cs b/src/ServiceControl.Transports.Tests/TestContextAppender.cs index 26a3a5645c..e3b9524253 100644 --- a/src/ServiceControl.Transports.Tests/TestContextAppender.cs +++ b/src/ServiceControl.Transports.Tests/TestContextAppender.cs @@ -1,87 +1,29 @@ namespace ServiceControl.Transport.Tests { using System; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using NUnit.Framework; - class TestContextAppender : ILog + class TestContextAppender(string categoryName) : ILogger { - public bool IsDebugEnabled => false; - public bool IsInfoEnabled => false; - public bool IsWarnEnabled => true; - public bool IsErrorEnabled => true; - public bool IsFatalEnabled => true; - - public void Debug(string message) => Log(message, LogLevel.Debug); - - public void Debug(string message, Exception exception) - { - var fullMessage = $"{message} {exception}"; - Log(fullMessage, LogLevel.Debug); - } - - public void DebugFormat(string format, params object[] args) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { - var fullMessage = string.Format(format, args); - Log(fullMessage, LogLevel.Debug); + if (IsEnabled(logLevel)) + { + TestContext.Out.WriteLine($"{categoryName}: {formatter(state, exception)}"); + } } + public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning; - public void Info(string message) => Log(message, LogLevel.Info); + public IDisposable BeginScope(TState state) where TState : notnull => Disposable.Instance; - public void Info(string message, Exception exception) + class Disposable : IDisposable { - var fullMessage = $"{message} {exception}"; - Log(fullMessage, LogLevel.Info); - } + public static Disposable Instance = new(); - public void InfoFormat(string format, params object[] args) - { - var fullMessage = string.Format(format, args); - Log(fullMessage, LogLevel.Info); + public void Dispose() + { + } } - - public void Warn(string message) => Log(message, LogLevel.Warn); - - public void Warn(string message, Exception exception) - { - var fullMessage = $"{message} {exception}"; - Log(fullMessage, LogLevel.Warn); - } - - public void WarnFormat(string format, params object[] args) - { - var fullMessage = string.Format(format, args); - Log(fullMessage, LogLevel.Warn); - } - - public void Error(string message) => Log(message, LogLevel.Error); - - public void Error(string message, Exception exception) - { - var fullMessage = $"{message} {exception}"; - Log(fullMessage, LogLevel.Error); - } - - public void ErrorFormat(string format, params object[] args) - { - var fullMessage = string.Format(format, args); - Log(fullMessage, LogLevel.Error); - } - - public void Fatal(string message) => Log(message, LogLevel.Fatal); - - public void Fatal(string message, Exception exception) - { - var fullMessage = $"{message} {exception}"; - Log(fullMessage, LogLevel.Fatal); - } - - public void FatalFormat(string format, params object[] args) - { - var fullMessage = string.Format(format, args); - Log(fullMessage, LogLevel.Fatal); - } - - static void Log(string message, LogLevel _) => TestContext.Out.WriteLine(message); } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs b/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs index 75d8dbfcef..9c5b4da728 100644 --- a/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs +++ b/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs @@ -1,12 +1,17 @@ namespace ServiceControl.Transport.Tests { - using System; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; class TestContextAppenderFactory : ILoggerFactory { - public ILog GetLogger(Type type) => GetLogger(type.FullName); + public void AddProvider(ILoggerProvider provider) + { + } - public ILog GetLogger(string name) => new TestContextAppender(); + public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName); + + public void Dispose() + { + } } } \ No newline at end of file diff --git a/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs b/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs index aa678c8b01..78a6aea1d7 100644 --- a/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs +++ b/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using NUnit.Framework; using Particular.Approvals; + using ServiceControl.Infrastructure; using ServiceControl.Transports; [TestFixture] @@ -16,6 +17,12 @@ public class TransportManifestLibraryTests const string transportType = "ServiceControl.Transports.ASBS.ASBSTransportCustomization, ServiceControl.Transports.ASBS"; const string transportAlias = "ServiceControl.Transports.AzureServiceBus.AzureServiceBusTransport, ServiceControl.Transports.AzureServiceBus"; + [SetUp] + public void SetUp() + { + LoggerUtil.LoggerFactory = new TestContextAppenderFactory(); + } + [Test] public void Should_find_transport_manifest_by_name() { diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index cd8c301137..4a769f63bb 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using NServiceBus; + using NServiceBus.Extensions.Logging; using NServiceBus.Logging; using NServiceBus.Transport; using NUnit.Framework; @@ -21,7 +22,7 @@ class TransportTestFixture public virtual async Task Setup() { //TODO remove LogManager usage - LogManager.UseFactory(new TestContextAppenderFactory()); + LogManager.UseFactory(new ExtensionsLoggerFactory(new TestContextAppenderFactory())); configuration = new TransportTestsConfiguration(); testCancellationTokenSource = Debugger.IsAttached ? new CancellationTokenSource() : new CancellationTokenSource(TestTimeout); registrations = []; From 66aaa0225579fce5193958868a94003f123b153a Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 10 Jun 2025 10:34:26 +1000 Subject: [PATCH 07/27] Switch to .NET logging --- .../CustomChecks/CheckDirtyMemory.cs | 14 ++++---- .../CustomChecks/CheckFreeDiskSpace.cs | 32 ++++++++--------- ...CheckMinimumStorageRequiredForIngestion.cs | 35 +++++++++---------- .../CustomChecks/CheckRavenDBIndexLag.cs | 20 ++++++----- .../RavenEmbeddedPersistenceLifecycle.cs | 8 ++--- .../RavenPersistenceConfiguration.cs | 22 +++++++----- .../LoggerUtil.cs | 27 ++++++++++++++ .../ServiceControlComponentRunner.cs | 3 +- .../Hosting/Commands/SetupCommand.cs | 8 ++--- .../MonitoredEndpointMessageTypeParser.cs | 7 ++-- .../Licensing/ActiveLicense.cs | 14 +++++--- .../Licensing/LicenseCheckHostedService.cs | 7 ++-- src/ServiceControl.Monitoring/Program.cs | 11 +++--- .../LegacyQueueLengthReportHandler.cs | 15 ++------ .../ServiceControl.Monitoring.csproj | 1 - 15 files changed, 118 insertions(+), 106 deletions(-) create mode 100644 src/ServiceControl.Infrastructure/LoggerUtil.cs diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs index 37731858d8..409b3d6df1 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs @@ -3,26 +3,24 @@ namespace ServiceControl.Audit.Persistence.RavenDB.CustomChecks; using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; -using NServiceBus.Logging; -class CheckDirtyMemory(MemoryInformationRetriever memoryInformationRetriever) : CustomCheck("RavenDB dirty memory", "ServiceControl.Audit Health", TimeSpan.FromMinutes(5)) +class CheckDirtyMemory(MemoryInformationRetriever memoryInformationRetriever, ILogger logger) : CustomCheck("RavenDB dirty memory", "ServiceControl.Audit Health", TimeSpan.FromMinutes(5)) { + public override async Task PerformCheck(CancellationToken cancellationToken = default) { var (isHighDirty, dirtyMemory) = await memoryInformationRetriever.GetMemoryInformation(cancellationToken); - Log.Debug($"RavenDB dirty memory value: {dirtyMemory}."); + logger.LogDebug("RavenDB dirty memory value: {DirtyMemory}.", dirtyMemory); if (isHighDirty) { - var message = $"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue."; - Log.Warn(message); - return CheckResult.Failed(message); + logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.", dirtyMemory); + return CheckResult.Failed($"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue."); } return CheckResult.Pass; } - - static readonly ILog Log = LogManager.GetLogger(); } \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs index 18705af5b9..923b6208d6 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs @@ -5,17 +5,18 @@ using System.IO; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using RavenDB; + using ServiceControl.Infrastructure; - class CheckFreeDiskSpace(DatabaseConfiguration databaseConfiguration) : CustomCheck("ServiceControl.Audit database", "Storage space", TimeSpan.FromMinutes(5)) + class CheckFreeDiskSpace(DatabaseConfiguration databaseConfiguration, ILogger logger) : CustomCheck("ServiceControl.Audit database", "Storage space", TimeSpan.FromMinutes(5)) { public override Task PerformCheck(CancellationToken cancellationToken = default) { - if (Logger.IsDebugEnabled) + if (logger.IsEnabled(LogLevel.Debug)) { - Logger.Debug($"Check ServiceControl data drive space remaining custom check starting. Threshold {percentageThreshold:P0}"); + logger.LogDebug("Check ServiceControl data drive space remaining custom check starting. Threshold {PercentageThreshold:P0}", percentageThreshold); } if (!databaseConfiguration.ServerConfiguration.UseEmbeddedServer) @@ -34,9 +35,9 @@ public override Task PerformCheck(CancellationToken cancellationTok var percentRemaining = (decimal)dataDriveInfo.AvailableFreeSpace / dataDriveInfo.TotalSize; - if (Logger.IsDebugEnabled) + if (logger.IsEnabled(LogLevel.Debug)) { - Logger.Debug($"Free space: {availableFreeSpace:N0}B | Total: {totalSpace:N0}B | Percent remaining {percentRemaining:P1}"); + logger.LogDebug("Free space: {AvailableFreeSpace:N0}B | Total: {TotalSpace:N0}B | Percent remaining {PercentRemaining:P1}", availableFreeSpace, totalSpace, percentRemaining); } return percentRemaining > percentageThreshold @@ -51,26 +52,22 @@ public static int Parse(IDictionary settings) thresholdValue = $"{DataSpaceRemainingThresholdDefault}"; } - string message; if (!int.TryParse(thresholdValue, out var threshold)) { - message = $"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} must be an integer."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} must be an integer.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} must be an integer."); } if (threshold < 0) { - message = $"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, minimum value is 0."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, minimum value is 0.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, minimum value is 0."); } if (threshold > 100) { - message = $"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, maximum value is 100."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, maximum value is 100.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, maximum value is 100."); } return threshold; @@ -78,8 +75,7 @@ public static int Parse(IDictionary settings) readonly string dataPathRoot = Path.GetPathRoot(databaseConfiguration.ServerConfiguration.DbPath); readonly decimal percentageThreshold = databaseConfiguration.DataSpaceRemainingThreshold / 100m; - + static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(); public const int DataSpaceRemainingThresholdDefault = 20; - static readonly ILog Logger = LogManager.GetLogger(typeof(CheckFreeDiskSpace)); } } \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs index 6d2fccbc38..56153b3169 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs @@ -5,19 +5,20 @@ using System.IO; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using RavenDB; + using ServiceControl.Infrastructure; - class CheckMinimumStorageRequiredForIngestion(MinimumRequiredStorageState stateHolder, DatabaseConfiguration databaseConfiguration) : CustomCheck("Audit Message Ingestion Process", "ServiceControl.Audit Health", TimeSpan.FromSeconds(5)) + class CheckMinimumStorageRequiredForIngestion(MinimumRequiredStorageState stateHolder, DatabaseConfiguration databaseConfiguration, ILogger logger) : CustomCheck("Audit Message Ingestion Process", "ServiceControl.Audit Health", TimeSpan.FromSeconds(5)) { public override Task PerformCheck(CancellationToken cancellationToken = default) { var percentageThreshold = databaseConfiguration.MinimumStorageLeftRequiredForIngestion / 100m; - if (Logger.IsDebugEnabled) + if (logger.IsEnabled(LogLevel.Debug)) { - Logger.Debug($"Check ServiceControl data drive space starting. Threshold {percentageThreshold:P0}"); + logger.LogDebug("Check ServiceControl data drive space starting. Threshold {PercentageThreshold:P0}", percentageThreshold); } // Should be checking UseEmbeddedServer but need to check DbPath instead for the ATT hack to work @@ -35,9 +36,9 @@ public override Task PerformCheck(CancellationToken cancellationTok var percentRemaining = (decimal)dataDriveInfo.AvailableFreeSpace / dataDriveInfo.TotalSize; - if (Logger.IsDebugEnabled) + if (logger.IsEnabled(LogLevel.Debug)) { - Logger.Debug($"Free space: {availableFreeSpace} | Total: {totalSpace} | Percent remaining {percentRemaining:P0}"); + logger.LogDebug("Free space: {AvailableFreeSpace} | Total: {TotalSpace} | Percent remaining {PercentRemaining:P0}", availableFreeSpace, totalSpace, percentRemaining); } if (percentRemaining > percentageThreshold) @@ -46,10 +47,9 @@ public override Task PerformCheck(CancellationToken cancellationTok return SuccessResult; } - var message = $"Audit message ingestion stopped! {percentRemaining:P0} disk space remaining on data drive '{dataDriveInfo.VolumeLabel} ({dataDriveInfo.RootDirectory})' on '{Environment.MachineName}'. This is less than {percentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} configuration setting."; - Logger.Warn(message); + logger.LogWarning("Audit message ingestion stopped! {PercentRemaining:P0} disk space remaining on data drive '{DataDriveInfoVolumeLabel} ({DataDriveInfoRootDirectory})' on '{EnvironmentMachineName}'. This is less than {PercentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenPersistenceConfigurationMinimumStorageLeftRequiredForIngestionKey} configuration setting.", percentRemaining, dataDriveInfo.VolumeLabel, dataDriveInfo.RootDirectory, Environment.MachineName, percentageThreshold, RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey); stateHolder.CanIngestMore = false; - return CheckResult.Failed(message); + return CheckResult.Failed($"Audit message ingestion stopped! {percentRemaining:P0} disk space remaining on data drive '{dataDriveInfo.VolumeLabel} ({dataDriveInfo.RootDirectory})' on '{Environment.MachineName}'. This is less than {percentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} configuration setting."); } public static int Parse(IDictionary settings) @@ -61,23 +61,20 @@ public static int Parse(IDictionary settings) if (!int.TryParse(thresholdValue, out var threshold)) { - var message = $"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} must be an integer."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationMinimumStorageLeftRequiredForIngestionKey} must be an integer.", RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey); + throw new Exception($"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} must be an integer."); } if (threshold < 0) { - var message = $"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationMinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0.", RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey); + throw new Exception($"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0."); } if (threshold > 100) { - var message = $"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100."; - Logger.Fatal(message); - throw new Exception(message); + Logger.LogCritical("{RavenPersistenceConfigurationMinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100.", RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey); + throw new Exception($"{RavenPersistenceConfiguration.MinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100."); } return threshold; @@ -85,6 +82,6 @@ public static int Parse(IDictionary settings) public const int MinimumStorageLeftRequiredForIngestionDefault = 5; static readonly Task SuccessResult = Task.FromResult(CheckResult.Pass); - static readonly ILog Logger = LogManager.GetLogger(typeof(CheckMinimumStorageRequiredForIngestion)); + static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs index 41f4347a71..193e384f2d 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs @@ -5,12 +5,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using Raven.Client.Documents.Operations; using ServiceControl.Audit.Persistence.RavenDB; + using ServiceControl.Infrastructure; - class CheckRavenDBIndexLag(IRavenDocumentStoreProvider documentStoreProvider) : CustomCheck("Audit Database Index Lag", "ServiceControl.Audit Health", TimeSpan.FromMinutes(5)) + class CheckRavenDBIndexLag(IRavenDocumentStoreProvider documentStoreProvider, ILogger logger) : CustomCheck("Audit Database Index Lag", "ServiceControl.Audit Health", TimeSpan.FromMinutes(5)) { public override async Task PerformCheck(CancellationToken cancellationToken = default) { @@ -20,7 +21,7 @@ public override async Task PerformCheck(CancellationToken cancellat CreateDiagnosticsLogEntry(statistics, indexes); - var indexCountWithTooMuchLag = CheckAndReportIndexesWithTooMuchIndexLag(indexes); + var indexCountWithTooMuchLag = CheckAndReportIndexesWithTooMuchIndexLag(indexes, logger); if (indexCountWithTooMuchLag > 0) { @@ -30,7 +31,7 @@ public override async Task PerformCheck(CancellationToken cancellat return CheckResult.Pass; } - static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) + static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes, ILogger logger) { int indexCountWithTooMuchLag = 0; @@ -43,12 +44,12 @@ static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) if (indexLag > IndexLagThresholdError) { indexCountWithTooMuchLag++; - Log.Error($"Index [{indexStats.Name}] IndexingLag {indexLag} is above error threshold ({IndexLagThresholdError}). Launch in maintenance mode to let indexes catch up."); + logger.LogError("Index [{IndexStatsName}] IndexingLag {IndexLag} is above error threshold ({IndexLagThresholdError}). Launch in maintenance mode to let indexes catch up.", indexStats.Name, indexLag, IndexLagThresholdError); } else if (indexLag > IndexLagThresholdWarning) { indexCountWithTooMuchLag++; - Log.Warn($"Index [{indexStats.Name}] IndexingLag {indexLag} is above warning threshold ({IndexLagThresholdWarning}). Launch in maintenance mode to let indexes catch up."); + logger.LogWarning("Index [{IndexStatsName}] IndexingLag {IndexLag} is above warning threshold ({IndexLagThresholdWarning}). Launch in maintenance mode to let indexes catch up.", indexStats.Name, indexLag, IndexLagThresholdWarning); } } } @@ -58,7 +59,7 @@ static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) static void CreateDiagnosticsLogEntry(DatabaseStatistics statistics, IndexInformation[] indexes) { - if (!Log.IsDebugEnabled) + if (!Logger.IsEnabled(LogLevel.Debug)) { return; } @@ -72,11 +73,12 @@ static void CreateDiagnosticsLogEntry(DatabaseStatistics statistics, IndexInform { report.AppendLine($"- Index [{indexStats.Name,-44}] State: {indexStats.State}, Stale: {indexStats.IsStale,-5}, Priority: {indexStats.Priority,-6}, LastIndexingTime: {indexStats.LastIndexingTime:u}"); } - Log.Debug(report.ToString()); + + Logger.LogDebug(report.ToString()); } static readonly TimeSpan IndexLagThresholdWarning = TimeSpan.FromMinutes(1); static readonly TimeSpan IndexLagThresholdError = TimeSpan.FromMinutes(10); - static readonly ILog Log = LogManager.GetLogger(); + static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs index f7f1ecee16..80bf05b742 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs @@ -6,12 +6,12 @@ namespace ServiceControl.Audit.Persistence.RavenDB using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client.Documents; using Raven.Client.Exceptions.Database; using ServiceControl.RavenDB; - sealed class RavenEmbeddedPersistenceLifecycle(DatabaseConfiguration databaseConfiguration, IHostApplicationLifetime lifetime) : IRavenPersistenceLifecycle, IRavenDocumentStoreProvider, IDisposable + sealed class RavenEmbeddedPersistenceLifecycle(DatabaseConfiguration databaseConfiguration, IHostApplicationLifetime lifetime, ILogger logger) : IRavenPersistenceLifecycle, IRavenDocumentStoreProvider, IDisposable { public async ValueTask GetDocumentStore(CancellationToken cancellationToken = default) { @@ -61,7 +61,7 @@ public async Task Initialize(CancellationToken cancellationToken = default) } catch (DatabaseLoadTimeoutException e) { - Log.Warn("Connecting to the embedded RavenDB database timed out. Retrying in 500ms...", e); + logger.LogWarning(e, "Connecting to the embedded RavenDB database timed out. Retrying in 500ms..."); await Task.Delay(500, cancellationToken); } } @@ -83,7 +83,5 @@ public void Dispose() IDocumentStore? documentStore; EmbeddedDatabase? database; readonly SemaphoreSlim initializeSemaphore = new(1, 1); - - static readonly ILog Log = LogManager.GetLogger(typeof(RavenEmbeddedPersistenceLifecycle)); } } diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs index b22003ceae..fc8aa2f281 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs @@ -5,7 +5,8 @@ using System.IO; using System.Reflection; using CustomChecks; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; + using ServiceControl.Infrastructure; public class RavenPersistenceConfiguration : IPersistenceConfiguration { @@ -141,15 +142,17 @@ static int GetExpirationProcessTimerInSeconds(PersistenceSettings settings) expirationProcessTimerInSeconds = int.Parse(expirationProcessTimerInSecondsString); } + var maxExpirationProcessTimerInSeconds = TimeSpan.FromHours(3).TotalSeconds; + if (expirationProcessTimerInSeconds < 0) { - Logger.Error($"ExpirationProcessTimerInSeconds cannot be negative. Defaulting to {ExpirationProcessTimerInSecondsDefault}"); + Logger.LogError("ExpirationProcessTimerInSeconds cannot be negative. Defaulting to {ExpirationProcessTimerInSecondsDefault}", ExpirationProcessTimerInSecondsDefault); return ExpirationProcessTimerInSecondsDefault; } - if (expirationProcessTimerInSeconds > TimeSpan.FromHours(3).TotalSeconds) + if (expirationProcessTimerInSeconds > maxExpirationProcessTimerInSeconds) { - Logger.Error($"ExpirationProcessTimerInSeconds cannot be larger than {TimeSpan.FromHours(3).TotalSeconds}. Defaulting to {ExpirationProcessTimerInSecondsDefault}"); + Logger.LogError("ExpirationProcessTimerInSeconds cannot be larger than {MaxExpirationProcessTimerInSeconds}. Defaulting to {ExpirationProcessTimerInSecondsDefault}", maxExpirationProcessTimerInSeconds, ExpirationProcessTimerInSecondsDefault); return ExpirationProcessTimerInSecondsDefault; } @@ -165,15 +168,17 @@ static int GetBulkInsertCommitTimeout(PersistenceSettings settings) bulkInsertCommitTimeoutInSeconds = int.Parse(bulkInsertCommitTimeoutString); } + var maxBulkInsertCommitTimeoutInSeconds = TimeSpan.FromHours(1).TotalSeconds; + if (bulkInsertCommitTimeoutInSeconds < 0) { - Logger.Error($"BulkInsertCommitTimeout cannot be negative. Defaulting to {BulkInsertCommitTimeoutInSecondsDefault}"); + Logger.LogError("BulkInsertCommitTimeout cannot be negative. Defaulting to {BulkInsertCommitTimeoutInSecondsDefault}", BulkInsertCommitTimeoutInSecondsDefault); return BulkInsertCommitTimeoutInSecondsDefault; } - if (bulkInsertCommitTimeoutInSeconds > TimeSpan.FromHours(1).TotalSeconds) + if (bulkInsertCommitTimeoutInSeconds > maxBulkInsertCommitTimeoutInSeconds) { - Logger.Error($"BulkInsertCommitTimeout cannot be larger than {TimeSpan.FromHours(1).TotalSeconds}. Defaulting to {BulkInsertCommitTimeoutInSecondsDefault}"); + Logger.LogError("BulkInsertCommitTimeout cannot be larger than {MaxBulkInsertCommitTimeoutInSeconds}. Defaulting to {BulkInsertCommitTimeoutInSecondsDefault}", maxBulkInsertCommitTimeoutInSeconds, BulkInsertCommitTimeoutInSecondsDefault); return BulkInsertCommitTimeoutInSecondsDefault; } @@ -193,9 +198,8 @@ static string GetLogPath(PersistenceSettings settings) return logPath; } - static readonly ILog Logger = LogManager.GetLogger(typeof(RavenPersistenceConfiguration)); - const int ExpirationProcessTimerInSecondsDefault = 600; const int BulkInsertCommitTimeoutInSecondsDefault = 60; + static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(); } } diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs new file mode 100644 index 0000000000..98aeb7d865 --- /dev/null +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -0,0 +1,27 @@ +namespace ServiceControl.Infrastructure +{ + using System; + using Microsoft.Extensions.Logging; + using NLog.Extensions.Logging; + + public static class LoggerUtil + { + public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) + { + loggingBuilder.AddNLog(); + loggingBuilder.SetMinimumLevel(level); + } + + public static ILogger CreateStaticLogger(LogLevel level = LogLevel.Information) + { + var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); + return factory.CreateLogger(); + } + + public static ILogger CreateStaticLogger(Type type, LogLevel level = LogLevel.Information) + { + var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); + return factory.CreateLogger(type); + } + } +} \ No newline at end of file diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index debc3ed629..212f1e03a1 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -18,6 +18,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.TestSupport using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; using NServiceBus.Logging; + using ServiceControl.Infrastructure; class ServiceControlComponentRunner( ITransportIntegration transportToUse, @@ -72,7 +73,7 @@ async Task InitializeServiceControl(ScenarioContext context) using (new DiagnosticTimer($"Creating infrastructure for {settings.InstanceName}")) { - var setupCommand = new SetupCommand(); + var setupCommand = new SetupCommand(LoggerUtil.CreateStaticLogger()); await setupCommand.Execute(new HostArguments([]), settings); } diff --git a/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs b/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs index 3bd7830438..d585434197 100644 --- a/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs +++ b/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs @@ -1,16 +1,16 @@ namespace ServiceControl.Monitoring { using System.Threading.Tasks; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Transports; - class SetupCommand : AbstractCommand + class SetupCommand(ILogger logger) : AbstractCommand { public override Task Execute(HostArguments args, Settings settings) { if (args.SkipQueueCreation) { - Logger.Info("Skipping queue creation"); + logger.LogInformation("Skipping queue creation"); return Task.CompletedTask; } @@ -19,7 +19,5 @@ public override Task Execute(HostArguments args, Settings settings) var transportCustomization = TransportFactory.Create(transportSettings); return transportCustomization.ProvisionQueues(transportSettings, []); } - - static readonly ILog Logger = LogManager.GetLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Http/Diagrams/MonitoredEndpointMessageTypeParser.cs b/src/ServiceControl.Monitoring/Http/Diagrams/MonitoredEndpointMessageTypeParser.cs index 3faa1e81c7..f089104b4f 100644 --- a/src/ServiceControl.Monitoring/Http/Diagrams/MonitoredEndpointMessageTypeParser.cs +++ b/src/ServiceControl.Monitoring/Http/Diagrams/MonitoredEndpointMessageTypeParser.cs @@ -3,7 +3,8 @@ namespace ServiceControl.Monitoring.Http.Diagrams using System; using System.Linq; using System.Reflection; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; + using ServiceControl.Infrastructure; public static class MonitoredEndpointMessageTypeParser { @@ -40,7 +41,7 @@ public static MonitoredEndpointMessageType Parse(string typeName) } catch (Exception e) { - Logger.Warn($"Error parsing message type: {typeName}.", e); + LoggerUtil.CreateStaticLogger(typeof(MonitoredEndpointMessageTypeParser)).LogWarning(e, "Error parsing message type: {typeName}.", typeName); } } @@ -50,7 +51,5 @@ public static MonitoredEndpointMessageType Parse(string typeName) TypeName = typeName }; } - - static readonly ILog Logger = LogManager.GetLogger(typeof(MonitoredEndpointMessageTypeParser)); } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Licensing/ActiveLicense.cs b/src/ServiceControl.Monitoring/Licensing/ActiveLicense.cs index a3a001e0ad..f5ca3be8bc 100644 --- a/src/ServiceControl.Monitoring/Licensing/ActiveLicense.cs +++ b/src/ServiceControl.Monitoring/Licensing/ActiveLicense.cs @@ -1,11 +1,15 @@ namespace ServiceControl.Monitoring.Licensing { - using global::ServiceControl.LicenseManagement; - using NServiceBus.Logging; + using ServiceControl.LicenseManagement; + using Microsoft.Extensions.Logging; public class ActiveLicense { - public ActiveLicense() => Refresh(); + public ActiveLicense(ILogger logger) + { + this.logger = logger; + Refresh(); + } public bool IsValid { get; set; } @@ -13,7 +17,7 @@ public class ActiveLicense public void Refresh() { - Logger.Debug("Refreshing ActiveLicense"); + logger.LogDebug("Refreshing ActiveLicense"); var detectedLicense = LicenseManager.FindLicense(); @@ -22,6 +26,6 @@ public void Refresh() Details = detectedLicense.Details; } - static readonly ILog Logger = LogManager.GetLogger(typeof(ActiveLicense)); + readonly ILogger logger; } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Licensing/LicenseCheckHostedService.cs b/src/ServiceControl.Monitoring/Licensing/LicenseCheckHostedService.cs index a5b10f73b5..b29e47fd05 100644 --- a/src/ServiceControl.Monitoring/Licensing/LicenseCheckHostedService.cs +++ b/src/ServiceControl.Monitoring/Licensing/LicenseCheckHostedService.cs @@ -4,10 +4,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using ServiceControl.Infrastructure.BackgroundTasks; - class LicenseCheckHostedService(ActiveLicense activeLicense, IAsyncTimer scheduler) : IHostedService + class LicenseCheckHostedService(ActiveLicense activeLicense, IAsyncTimer scheduler, ILogger logger) : IHostedService { public Task StartAsync(CancellationToken cancellationToken) { @@ -16,7 +16,7 @@ public Task StartAsync(CancellationToken cancellationToken) { activeLicense.Refresh(); return ScheduleNextExecutionTask; - }, due, due, ex => Logger.Error("Unhandled error while refreshing the license.", ex)); + }, due, due, ex => logger.LogError(ex, "Unhandled error while refreshing the license.")); return Task.CompletedTask; } @@ -24,7 +24,6 @@ public Task StartAsync(CancellationToken cancellationToken) TimerJob timer; - static readonly ILog Logger = LogManager.GetLogger(); static readonly Task ScheduleNextExecutionTask = Task.FromResult(TimerJobExecutionResult.ScheduleNextExecution); } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Program.cs b/src/ServiceControl.Monitoring/Program.cs index 8620eba3cc..fa34bf4978 100644 --- a/src/ServiceControl.Monitoring/Program.cs +++ b/src/ServiceControl.Monitoring/Program.cs @@ -1,13 +1,13 @@ using System; using System.Reflection; -using NServiceBus.Logging; +using Microsoft.Extensions.Logging; using ServiceControl.Configuration; using ServiceControl.Infrastructure; using ServiceControl.Monitoring; try { - AppDomain.CurrentDomain.UnhandledException += (s, e) => LogManager.GetLogger(typeof(Program)).Error("Unhandled exception was caught.", e.ExceptionObject as Exception); + AppDomain.CurrentDomain.UnhandledException += (s, e) => LoggerUtil.CreateStaticLogger().LogError(e.ExceptionObject as Exception, "Unhandled exception was caught."); // Hack: See https://github.com/Particular/ServiceControl/issues/4392 var exitCode = await IntegratedSetup.Run(); @@ -32,12 +32,11 @@ } catch (Exception ex) { - NLog.LogManager.GetCurrentClassLogger().Fatal(ex, "Unrecoverable error"); + LoggerUtil.CreateStaticLogger().LogCritical(ex, "Unrecoverable error"); throw; } finally { // The following log statement is meant to leave a trail in the logs to determine if the process was killed - NLog.LogManager.GetCurrentClassLogger().Info("Shutdown complete"); - NLog.LogManager.Shutdown(); -} \ No newline at end of file + LoggerUtil.CreateStaticLogger().LogInformation("Shutdown complete"); +} diff --git a/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs b/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs index 82a72e4a8b..93d905558d 100644 --- a/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs +++ b/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs @@ -5,33 +5,24 @@ using System.Threading; using System.Threading.Tasks; using Infrastructure; + using Microsoft.Extensions.Logging; using NServiceBus; - using NServiceBus.Logging; using NServiceBus.Metrics; - class LegacyQueueLengthReportHandler : IHandleMessages + class LegacyQueueLengthReportHandler(LegacyQueueLengthReportHandler.LegacyQueueLengthEndpoints legacyEndpoints, ILogger logger) : IHandleMessages { - public LegacyQueueLengthReportHandler(LegacyQueueLengthEndpoints legacyEndpoints) - { - this.legacyEndpoints = legacyEndpoints; - } - public Task Handle(MetricReport message, IMessageHandlerContext context) { var endpointInstanceId = EndpointInstanceId.From(context.MessageHeaders); if (legacyEndpoints.TryAdd(endpointInstanceId.InstanceId)) { - Logger.Warn($"Legacy queue length report received from {endpointInstanceId.InstanceName} instance of {endpointInstanceId.EndpointName}"); + logger.LogWarning("Legacy queue length report received from {EndpointInstanceIdInstanceName} instance of {EndpointInstanceIdEndpointName}", endpointInstanceId.InstanceName, endpointInstanceId.EndpointName); } return Task.CompletedTask; } - LegacyQueueLengthEndpoints legacyEndpoints; - - static readonly ILog Logger = LogManager.GetLogger(typeof(LegacyQueueLengthReportHandler)); - public class LegacyQueueLengthEndpoints { public bool TryAdd(string id) diff --git a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj index 35246ea1b8..1a9b705469 100644 --- a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj +++ b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj @@ -24,7 +24,6 @@ - From e2196e6fbb2f591e82a276e2687acd6ca070022e Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Thu, 12 Jun 2025 17:08:39 +1000 Subject: [PATCH 08/27] Work in progress --- src/Directory.Packages.props | 4 +- .../ServiceControlComponentRunner.cs | 2 +- .../ServiceControlComponentRunner.cs | 3 +- .../CustomChecks/CheckFreeDiskSpace.cs | 10 ++-- .../RavenPersistenceConfiguration.cs | 2 +- .../HostApplicationBuilderExtensions.cs | 2 +- .../Infrastructure/WebApi/RootController.cs | 2 +- .../LoggerUtil.cs | 5 +- .../LoggingConfigurator.cs | 10 +++- .../LoggingSettings.cs | 55 +++++++++++-------- .../ServiceControl.Infrastructure.csproj | 2 + .../ServiceControlComponentRunner.cs | 3 +- .../HostApplicationBuilderExtensions.cs | 6 +- .../Hosting/Commands/SetupCommand.cs | 5 +- src/ServiceControl.Monitoring/Program.cs | 8 ++- .../ServiceControl.Monitoring.csproj | 1 + .../HostApplicationBuilderExtensions.cs | 2 +- .../Infrastructure/Api/ConfigurationApi.cs | 2 +- 18 files changed, 72 insertions(+), 52 deletions(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 60eb7072c9..dfd35a5f78 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -24,6 +24,7 @@ + @@ -63,6 +64,7 @@ + @@ -91,4 +93,4 @@ - + \ No newline at end of file diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 19bbe6b57a..f1b3e58a01 100644 --- a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -15,7 +15,7 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; - using NLog; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; diff --git a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 0866b504db..ce71680748 100644 --- a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -17,6 +17,7 @@ namespace ServiceControl.Audit.AcceptanceTests.TestSupport using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Hosting; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; @@ -43,7 +44,7 @@ async Task InitializeServiceControl(ScenarioContext context) var logPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(logPath); - var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace, defaultLevel: NLog.LogLevel.Debug, logPath: logPath); + var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace, defaultLevel: LogLevel.Debug, logPath: logPath); settings = new Settings(transportToUse.TypeName, persistenceToUse.PersistenceType, loggingSettings) { diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs index 923b6208d6..45efbac8e0 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs @@ -8,7 +8,6 @@ using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; using RavenDB; - using ServiceControl.Infrastructure; class CheckFreeDiskSpace(DatabaseConfiguration databaseConfiguration, ILogger logger) : CustomCheck("ServiceControl.Audit database", "Storage space", TimeSpan.FromMinutes(5)) { @@ -45,7 +44,7 @@ public override Task PerformCheck(CancellationToken cancellationTok : CheckResult.Failed($"{percentRemaining:P0} disk space remaining on data drive '{dataDriveInfo.VolumeLabel} ({dataDriveInfo.RootDirectory})' on '{Environment.MachineName}'."); } - public static int Parse(IDictionary settings) + public static int Parse(IDictionary settings, ILogger logger) { if (!settings.TryGetValue(RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey, out var thresholdValue)) { @@ -54,19 +53,19 @@ public static int Parse(IDictionary settings) if (!int.TryParse(thresholdValue, out var threshold)) { - Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} must be an integer.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} must be an integer.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} must be an integer."); } if (threshold < 0) { - Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, minimum value is 0.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, minimum value is 0.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, minimum value is 0."); } if (threshold > 100) { - Logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, maximum value is 100.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, maximum value is 100.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, maximum value is 100."); } @@ -75,7 +74,6 @@ public static int Parse(IDictionary settings) readonly string dataPathRoot = Path.GetPathRoot(databaseConfiguration.ServerConfiguration.DbPath); readonly decimal percentageThreshold = databaseConfiguration.DataSpaceRemainingThreshold / 100m; - static readonly ILogger Logger = LoggerUtil.CreateStaticLogger(); public const int DataSpaceRemainingThresholdDefault = 20; } } \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs index fc8aa2f281..3611a3f646 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs @@ -114,7 +114,7 @@ internal static DatabaseConfiguration GetDatabaseConfiguration(PersistenceSettin serverConfiguration = new ServerConfiguration(dbPath, serverUrl, logPath, logsMode); } - var dataSpaceRemainingThreshold = CheckFreeDiskSpace.Parse(settings.PersisterSpecificSettings); + var dataSpaceRemainingThreshold = CheckFreeDiskSpace.Parse(settings.PersisterSpecificSettings, Logger); var minimumStorageLeftRequiredForIngestion = CheckMinimumStorageRequiredForIngestion.Parse(settings.PersisterSpecificSettings); var expirationProcessTimerInSeconds = GetExpirationProcessTimerInSeconds(settings); diff --git a/src/ServiceControl.Audit/HostApplicationBuilderExtensions.cs b/src/ServiceControl.Audit/HostApplicationBuilderExtensions.cs index ccacf5db1c..f1bbebb1d7 100644 --- a/src/ServiceControl.Audit/HostApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Audit/HostApplicationBuilderExtensions.cs @@ -41,7 +41,7 @@ public static void AddServiceControlAudit(this IHostApplicationBuilder builder, builder.Logging.ClearProviders(); builder.Logging.AddNLog(); - builder.Logging.SetMinimumLevel(settings.LoggingSettings.ToHostLogLevel()); + builder.Logging.SetMinimumLevel(settings.LoggingSettings.LogLevel); var services = builder.Services; var transportSettings = settings.ToTransportSettings(); diff --git a/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs b/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs index 42c53825d3..159e8c6d49 100644 --- a/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs +++ b/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs @@ -51,7 +51,7 @@ public OkObjectResult Config() Logging = new { settings.LoggingSettings.LogPath, - LoggingLevel = settings.LoggingSettings.LogLevel.Name + LoggingLevel = settings.LoggingSettings.LogLevel } }, DataRetention = new diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 98aeb7d865..3fac64d05a 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -9,13 +9,16 @@ public static class LoggerUtil public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) { loggingBuilder.AddNLog(); + loggingBuilder.AddSeq(); loggingBuilder.SetMinimumLevel(level); } public static ILogger CreateStaticLogger(LogLevel level = LogLevel.Information) { var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); - return factory.CreateLogger(); + var logger = factory.CreateLogger(); + logger.LogError("JTD: This is a test log message."); + return logger; } public static ILogger CreateStaticLogger(Type type, LogLevel level = LogLevel.Information) diff --git a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs index f32c84918c..1e505963da 100644 --- a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs +++ b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs @@ -60,11 +60,15 @@ public static void ConfigureLogging(LoggingSettings loggingSettings) nlogConfig.LoggingRules.Add(aspNetCoreRule); nlogConfig.LoggingRules.Add(httpClientRule); - nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, consoleTarget)); + // HACK: Fix LogLevel to Info for testing purposes only. + // nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, consoleTarget)); + nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, consoleTarget)); if (!AppEnvironment.RunningInContainer) { - nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, fileTarget)); + // HACK: Fix LogLevel to Info for testing purposes only. + //nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, fileTarget)); + nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, fileTarget)); } NLog.LogManager.Configuration = nlogConfig; @@ -74,7 +78,7 @@ public static void ConfigureLogging(LoggingSettings loggingSettings) var logger = LogManager.GetLogger("LoggingConfiguration"); var logEventInfo = new LogEventInfo { TimeStamp = DateTime.UtcNow }; var loggingTo = AppEnvironment.RunningInContainer ? "console" : fileTarget.FileName.Render(logEventInfo); - logger.InfoFormat("Logging to {0} with LogLevel '{1}'", loggingTo, loggingSettings.LogLevel.Name); + logger.InfoFormat("Logging to {0} with LogLevel '{1}'", loggingTo, LogLevel.Info.Name); } const long megaByte = 1024 * 1024; diff --git a/src/ServiceControl.Infrastructure/LoggingSettings.cs b/src/ServiceControl.Infrastructure/LoggingSettings.cs index 55282759a3..dd9fc18008 100644 --- a/src/ServiceControl.Infrastructure/LoggingSettings.cs +++ b/src/ServiceControl.Infrastructure/LoggingSettings.cs @@ -1,21 +1,19 @@ namespace ServiceControl.Infrastructure; using System; +using System.Collections.Generic; using System.IO; -using NLog; -using NLog.Common; +using Microsoft.Extensions.Logging; using ServiceControl.Configuration; -public class LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLevel = null, string logPath = null) +public class LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLevel = LogLevel.Information, string logPath = null) { public LogLevel LogLevel { get; } = InitializeLogLevel(rootNamespace, defaultLevel); - public string LogPath { get; } = SettingsReader.Read(rootNamespace, "LogPath", Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); + public string LogPath { get; } = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); static LogLevel InitializeLogLevel(SettingsRootNamespace rootNamespace, LogLevel defaultLevel) { - defaultLevel ??= LogLevel.Info; - var levelText = SettingsReader.Read(rootNamespace, logLevelKey); if (string.IsNullOrWhiteSpace(levelText)) @@ -23,31 +21,40 @@ static LogLevel InitializeLogLevel(SettingsRootNamespace rootNamespace, LogLevel return defaultLevel; } - try - { - return LogLevel.FromString(levelText); - } - catch - { - InternalLogger.Warn($"Failed to parse {logLevelKey} setting. Defaulting to {defaultLevel.Name}."); - return defaultLevel; - } + return ParseLogLevel(levelText, defaultLevel); } // SC installer always populates LogPath in app.config on installation/change/upgrade so this will only be used when // debugging or if the entry is removed manually. In those circumstances default to the folder containing the exe static string DefaultLogLocation() => Path.Combine(AppContext.BaseDirectory, ".logs"); - public Microsoft.Extensions.Logging.LogLevel ToHostLogLevel() => LogLevel switch + // This is not a complete mapping of NLog levels, just the ones that are different. + static readonly Dictionary NLogAliases = + new(StringComparer.OrdinalIgnoreCase) + { + ["info"] = LogLevel.Information, + ["warn"] = LogLevel.Warning, + ["fatal"] = LogLevel.Critical, + ["off"] = LogLevel.None + }; + + static LogLevel ParseLogLevel(string value, LogLevel defaultLevel) { - _ when LogLevel == LogLevel.Trace => Microsoft.Extensions.Logging.LogLevel.Trace, - _ when LogLevel == LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug, - _ when LogLevel == LogLevel.Info => Microsoft.Extensions.Logging.LogLevel.Information, - _ when LogLevel == LogLevel.Warn => Microsoft.Extensions.Logging.LogLevel.Warning, - _ when LogLevel == LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error, - _ when LogLevel == LogLevel.Fatal => Microsoft.Extensions.Logging.LogLevel.Critical, - _ => Microsoft.Extensions.Logging.LogLevel.None - }; + if (Enum.TryParse(value, ignoreCase: true, out LogLevel parsedLevel)) + { + return parsedLevel; + } + + if (NLogAliases.TryGetValue(value.Trim(), out parsedLevel)) + { + return parsedLevel; + } + + LoggerUtil.CreateStaticLogger().LogWarning("Failed to parse {LogLevelKey} setting. Defaulting to {DefaultLevel}.", logLevelKey, defaultLevel); + + return defaultLevel; + } const string logLevelKey = "LogLevel"; + const string logPathKey = "LogPath"; } \ No newline at end of file diff --git a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj index ea352f1711..37332ed734 100644 --- a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj +++ b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj @@ -9,9 +9,11 @@ + + \ No newline at end of file diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 212f1e03a1..debc3ed629 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -18,7 +18,6 @@ namespace ServiceControl.Monitoring.AcceptanceTests.TestSupport using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; using NServiceBus.Logging; - using ServiceControl.Infrastructure; class ServiceControlComponentRunner( ITransportIntegration transportToUse, @@ -73,7 +72,7 @@ async Task InitializeServiceControl(ScenarioContext context) using (new DiagnosticTimer($"Creating infrastructure for {settings.InstanceName}")) { - var setupCommand = new SetupCommand(LoggerUtil.CreateStaticLogger()); + var setupCommand = new SetupCommand(); await setupCommand.Execute(new HostArguments([]), settings); } diff --git a/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs b/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs index 90adce523d..7bda9a78ab 100644 --- a/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs @@ -22,6 +22,7 @@ namespace ServiceControl.Monitoring; using NServiceBus.Features; using NServiceBus.Transport; using QueueLength; +using ServiceControl.Infrastructure; using Timings; using Transports; @@ -31,9 +32,8 @@ public static void AddServiceControlMonitoring(this IHostApplicationBuilder host Func onCriticalError, Settings settings, EndpointConfiguration endpointConfiguration) { - hostBuilder.Logging.ClearProviders(); - hostBuilder.Logging.AddNLog(); - hostBuilder.Logging.SetMinimumLevel(settings.LoggingSettings.ToHostLogLevel()); + hostBuilder.Services.AddLogging(); + hostBuilder.Logging.BuildLogger(settings.LoggingSettings.LogLevel); var services = hostBuilder.Services; diff --git a/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs b/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs index d585434197..22a84b27f7 100644 --- a/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs +++ b/src/ServiceControl.Monitoring/Hosting/Commands/SetupCommand.cs @@ -2,15 +2,16 @@ namespace ServiceControl.Monitoring { using System.Threading.Tasks; using Microsoft.Extensions.Logging; + using ServiceControl.Infrastructure; using Transports; - class SetupCommand(ILogger logger) : AbstractCommand + class SetupCommand : AbstractCommand { public override Task Execute(HostArguments args, Settings settings) { if (args.SkipQueueCreation) { - logger.LogInformation("Skipping queue creation"); + LoggerUtil.CreateStaticLogger().LogInformation("Skipping queue creation"); return Task.CompletedTask; } diff --git a/src/ServiceControl.Monitoring/Program.cs b/src/ServiceControl.Monitoring/Program.cs index fa34bf4978..5aaa6f8c35 100644 --- a/src/ServiceControl.Monitoring/Program.cs +++ b/src/ServiceControl.Monitoring/Program.cs @@ -5,9 +5,11 @@ using ServiceControl.Infrastructure; using ServiceControl.Monitoring; +var logger = LoggerUtil.CreateStaticLogger(); + try { - AppDomain.CurrentDomain.UnhandledException += (s, e) => LoggerUtil.CreateStaticLogger().LogError(e.ExceptionObject as Exception, "Unhandled exception was caught."); + AppDomain.CurrentDomain.UnhandledException += (s, e) => logger.LogError(e.ExceptionObject as Exception, "Unhandled exception was caught."); // Hack: See https://github.com/Particular/ServiceControl/issues/4392 var exitCode = await IntegratedSetup.Run(); @@ -32,11 +34,11 @@ } catch (Exception ex) { - LoggerUtil.CreateStaticLogger().LogCritical(ex, "Unrecoverable error"); + logger.LogCritical(ex, "Unrecoverable error"); throw; } finally { // The following log statement is meant to leave a trail in the logs to determine if the process was killed - LoggerUtil.CreateStaticLogger().LogInformation("Shutdown complete"); + logger.LogInformation("Shutdown complete"); } diff --git a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj index 1a9b705469..9fbcf67af7 100644 --- a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj +++ b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj @@ -25,6 +25,7 @@ + diff --git a/src/ServiceControl/HostApplicationBuilderExtensions.cs b/src/ServiceControl/HostApplicationBuilderExtensions.cs index 50d0733fb9..76140a95ea 100644 --- a/src/ServiceControl/HostApplicationBuilderExtensions.cs +++ b/src/ServiceControl/HostApplicationBuilderExtensions.cs @@ -46,7 +46,7 @@ public static void AddServiceControl(this IHostApplicationBuilder hostBuilder, S logging.ClearProviders(); //HINT: configuration used by NLog comes from LoggingConfigurator.cs logging.AddNLog(); - logging.SetMinimumLevel(settings.LoggingSettings.ToHostLogLevel()); + logging.SetMinimumLevel(settings.LoggingSettings.LogLevel); var services = hostBuilder.Services; var transportSettings = settings.ToTransportSettings(); diff --git a/src/ServiceControl/Infrastructure/Api/ConfigurationApi.cs b/src/ServiceControl/Infrastructure/Api/ConfigurationApi.cs index fa06e80bc9..f8af272eb4 100644 --- a/src/ServiceControl/Infrastructure/Api/ConfigurationApi.cs +++ b/src/ServiceControl/Infrastructure/Api/ConfigurationApi.cs @@ -60,7 +60,7 @@ public Task GetConfig(CancellationToken cancellationToken) Logging = new { settings.LoggingSettings.LogPath, - LoggingLevel = settings.LoggingSettings.LogLevel.Name + LoggingLevel = settings.LoggingSettings.LogLevel } }, DataRetention = new From e9f287e1af3e39087ca5332410898b6d714de941 Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Fri, 13 Jun 2025 11:45:22 +1000 Subject: [PATCH 09/27] Remove test code --- src/ServiceControl.Infrastructure/LoggerUtil.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 3fac64d05a..623775e202 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -16,9 +16,7 @@ public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel lev public static ILogger CreateStaticLogger(LogLevel level = LogLevel.Information) { var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); - var logger = factory.CreateLogger(); - logger.LogError("JTD: This is a test log message."); - return logger; + return factory.CreateLogger(); } public static ILogger CreateStaticLogger(Type type, LogLevel level = LogLevel.Information) From 9b97c92d59daf0bc156f269bdc8ee47249e8552e Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 17 Jun 2025 10:06:13 +1000 Subject: [PATCH 10/27] Improve logging format for storage space details --- .../CustomChecks/CheckMinimumStorageRequiredForIngestion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs index 56153b3169..033a99fbbe 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs @@ -38,7 +38,7 @@ public override Task PerformCheck(CancellationToken cancellationTok if (logger.IsEnabled(LogLevel.Debug)) { - logger.LogDebug("Free space: {AvailableFreeSpace} | Total: {TotalSpace} | Percent remaining {PercentRemaining:P0}", availableFreeSpace, totalSpace, percentRemaining); + logger.LogDebug("Free space: {AvailableFreeSpace:N0}B | Total: {TotalSpace:N0}B | Percent remaining {PercentRemaining:P0}", availableFreeSpace, totalSpace, percentRemaining); } if (percentRemaining > percentageThreshold) From 005968d492cc02852c676a1c41e146c52fe676bb Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 17 Jun 2025 10:10:46 +1000 Subject: [PATCH 11/27] Properly shutdown NLog in Program.cs --- src/ServiceControl.Monitoring/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ServiceControl.Monitoring/Program.cs b/src/ServiceControl.Monitoring/Program.cs index 5aaa6f8c35..7a618a381f 100644 --- a/src/ServiceControl.Monitoring/Program.cs +++ b/src/ServiceControl.Monitoring/Program.cs @@ -41,4 +41,5 @@ { // The following log statement is meant to leave a trail in the logs to determine if the process was killed logger.LogInformation("Shutdown complete"); + NLog.LogManager.Shutdown(); } From 49ba86c1c1af137403b646ebd559811a8bfabea5 Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 17 Jun 2025 10:52:10 +1000 Subject: [PATCH 12/27] Remove Seq logging and prepare for .NET logging migration --- src/ServiceControl.Infrastructure/LoggerUtil.cs | 1 - .../LoggingConfigurator.cs | 11 +++++++---- .../ServiceControl.Infrastructure.csproj | 1 - .../ServiceControl.Monitoring.csproj | 1 - 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 623775e202..98aeb7d865 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -9,7 +9,6 @@ public static class LoggerUtil public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) { loggingBuilder.AddNLog(); - loggingBuilder.AddSeq(); loggingBuilder.SetMinimumLevel(level); } diff --git a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs index 1e505963da..5ca1c06c9b 100644 --- a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs +++ b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs @@ -12,6 +12,7 @@ namespace ServiceControl.Infrastructure using LogManager = NServiceBus.Logging.LogManager; + // TODO: Migrate from NLog to .NET logging public static class LoggingConfigurator { public static void ConfigureLogging(LoggingSettings loggingSettings) @@ -60,14 +61,16 @@ public static void ConfigureLogging(LoggingSettings loggingSettings) nlogConfig.LoggingRules.Add(aspNetCoreRule); nlogConfig.LoggingRules.Add(httpClientRule); - // HACK: Fix LogLevel to Info for testing purposes only. - // nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, consoleTarget)); + // HACK: Fixed LogLevel to Info for testing purposes only. + // Migrate to .NET logging and change back to loggingSettings.LogLevel. + // nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, consoleTarget)); nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, consoleTarget)); if (!AppEnvironment.RunningInContainer) { - // HACK: Fix LogLevel to Info for testing purposes only. - //nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, fileTarget)); + // HACK: Fixed LogLevel to Info for testing purposes only. + // Migrate to .NET logging and change back to loggingSettings.LogLevel. + // nlogConfig.LoggingRules.Add(new LoggingRule("*", loggingSettings.LogLevel, fileTarget)); nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, fileTarget)); } diff --git a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj index 37332ed734..29f38a7373 100644 --- a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj +++ b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj @@ -13,7 +13,6 @@ - \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj index 9fbcf67af7..1a9b705469 100644 --- a/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj +++ b/src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj @@ -25,7 +25,6 @@ - From 938c963fe4cdf413c91586365141edf193fd7db4 Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 17 Jun 2025 12:05:17 +1000 Subject: [PATCH 13/27] Update LogLevel format --- .../APIApprovals.PlatformSampleSettings.approved.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt b/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt index f718f461aa..7113c06339 100644 --- a/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt +++ b/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt @@ -1,9 +1,6 @@ { "LoggingSettings": { - "LogLevel": { - "Name": "Info", - "Ordinal": 2 - }, + "LogLevel": "Information", "LogPath": "C:\\Logs" }, "MessageFilter": null, From fb7f77e2b255ca037398c6259dbced9678638096 Mon Sep 17 00:00:00 2001 From: JasonTaylorDev Date: Tue, 17 Jun 2025 12:22:18 +1000 Subject: [PATCH 14/27] Update LogLevel format in logging settings --- .../SettingsTests.PlatformSampleSettings.approved.txt | 5 +---- .../APIApprovals.PlatformSampleSettings.approved.txt | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/ServiceControl.Monitoring.UnitTests/ApprovalFiles/SettingsTests.PlatformSampleSettings.approved.txt b/src/ServiceControl.Monitoring.UnitTests/ApprovalFiles/SettingsTests.PlatformSampleSettings.approved.txt index 5d32f42fbb..070234384e 100644 --- a/src/ServiceControl.Monitoring.UnitTests/ApprovalFiles/SettingsTests.PlatformSampleSettings.approved.txt +++ b/src/ServiceControl.Monitoring.UnitTests/ApprovalFiles/SettingsTests.PlatformSampleSettings.approved.txt @@ -1,9 +1,6 @@ { "LoggingSettings": { - "LogLevel": { - "Name": "Info", - "Ordinal": 2 - }, + "LogLevel": "Information", "LogPath": "C:\\Logs" }, "InstanceName": "Particular.Monitoring", diff --git a/src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt b/src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt index a23480af26..246f3e5678 100644 --- a/src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt +++ b/src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.PlatformSampleSettings.approved.txt @@ -1,9 +1,6 @@ { "LoggingSettings": { - "LogLevel": { - "Name": "Info", - "Ordinal": 2 - }, + "LogLevel": "Information", "LogPath": "C:\\Logs" }, "NotificationsFilter": null, From 07d560604369a142746471b3834f1ee34f239771 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Tue, 17 Jun 2025 15:38:53 +0800 Subject: [PATCH 15/27] enable adding test logging provider as part of loggerutils and create framework for settings driven logger selection --- .../LoggerUtil.cs | 35 +++++++++++++------ .../ServiceControl.Infrastructure.csproj | 1 + .../TestLogger}/TestContextAppender.cs | 2 +- .../TestLogger}/TestContextAppenderFactory.cs | 4 +-- .../TestLogger/TestContextProvider.cs | 14 ++++++++ .../FullEndpointTestFixture.cs | 2 +- .../ServiceControl.Transports.Tests.csproj | 1 + .../TransportManifestLibraryTests.cs | 2 +- .../TransportTestFixture.cs | 1 + 9 files changed, 46 insertions(+), 16 deletions(-) rename src/{ServiceControl.Transports.Tests => ServiceControl.Infrastructure/TestLogger}/TestContextAppender.cs (94%) rename src/{ServiceControl.Transports.Tests => ServiceControl.Infrastructure/TestLogger}/TestContextAppenderFactory.cs (71%) create mode 100644 src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 0757d17fa0..34fc16beb1 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -1,38 +1,51 @@ namespace ServiceControl.Infrastructure { using System; + using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; + using ServiceControl.Infrastructure.TestLogger; + + [Flags] + public enum Loggers + { + None = 0, + Test = 1 << 0, + NLog = 1 << 1, + Seq = 1 << 2, + } public static class LoggerUtil { - /// - /// used for tests - /// - public static ILoggerFactory LoggerFactory { private get; set; } + public static Loggers ActiveLoggers { private get; set; } = Loggers.None; public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) { - if (LoggerFactory != null) + if ((Loggers.Test & ActiveLoggers) == Loggers.Test) + { + loggingBuilder.Services.AddSingleton(new TestContextProvider()); + } + if ((Loggers.NLog & ActiveLoggers) == Loggers.NLog) + { + loggingBuilder.AddNLog(); + } + if ((Loggers.Seq & ActiveLoggers) == Loggers.Seq) { - return; + loggingBuilder.AddSeq(); } - //TODO: can we get these from settings too? - loggingBuilder.AddNLog(); - loggingBuilder.AddSeq(); loggingBuilder.SetMinimumLevel(level); } public static ILogger CreateStaticLogger(LogLevel level = LogLevel.Information) { - var factory = LoggerFactory ?? Microsoft.Extensions.Logging.LoggerFactory.Create(configure => configure.BuildLogger(level)); + var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); return factory.CreateLogger(); } public static ILogger CreateStaticLogger(Type type, LogLevel level = LogLevel.Information) { - var factory = LoggerFactory ?? Microsoft.Extensions.Logging.LoggerFactory.Create(configure => configure.BuildLogger(level)); + var factory = LoggerFactory.Create(configure => configure.BuildLogger(level)); return factory.CreateLogger(type); } } diff --git a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj index 467cca8759..b32d80b1fa 100644 --- a/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj +++ b/src/ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj @@ -15,6 +15,7 @@ + diff --git a/src/ServiceControl.Transports.Tests/TestContextAppender.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs similarity index 94% rename from src/ServiceControl.Transports.Tests/TestContextAppender.cs rename to src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs index e3b9524253..c353a3b60a 100644 --- a/src/ServiceControl.Transports.Tests/TestContextAppender.cs +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs @@ -1,4 +1,4 @@ -namespace ServiceControl.Transport.Tests +namespace ServiceControl.Infrastructure.TestLogger { using System; using Microsoft.Extensions.Logging; diff --git a/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs similarity index 71% rename from src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs rename to src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs index 9c5b4da728..98e1d683fb 100644 --- a/src/ServiceControl.Transports.Tests/TestContextAppenderFactory.cs +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs @@ -1,8 +1,8 @@ -namespace ServiceControl.Transport.Tests +namespace ServiceControl.Infrastructure.TestLogger { using Microsoft.Extensions.Logging; - class TestContextAppenderFactory : ILoggerFactory + public class TestContextAppenderFactory : ILoggerFactory { public void AddProvider(ILoggerProvider provider) { diff --git a/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs new file mode 100644 index 0000000000..e879c814a3 --- /dev/null +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs @@ -0,0 +1,14 @@ +namespace ServiceControl.Infrastructure.TestLogger +{ + using Microsoft.Extensions.Logging; + + public class TestContextProvider : ILoggerProvider + { + public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName); + + public void Dispose() + { + + } + } +} diff --git a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs index f2c4d13313..c1034d05f2 100644 --- a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs @@ -12,7 +12,7 @@ class FullEndpointTestFixture [SetUp] public virtual async Task Setup() { - LoggerUtil.LoggerFactory = new TestContextAppenderFactory(); + LoggerUtil.ActiveLoggers = Loggers.Test; configuration = new TransportTestsConfiguration(); var queueSuffix = $"-{System.IO.Path.GetRandomFileName().Replace(".", string.Empty)}"; diff --git a/src/ServiceControl.Transports.Tests/ServiceControl.Transports.Tests.csproj b/src/ServiceControl.Transports.Tests/ServiceControl.Transports.Tests.csproj index 8c7d0e9e78..aedb05ec31 100644 --- a/src/ServiceControl.Transports.Tests/ServiceControl.Transports.Tests.csproj +++ b/src/ServiceControl.Transports.Tests/ServiceControl.Transports.Tests.csproj @@ -5,6 +5,7 @@ + diff --git a/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs b/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs index 78a6aea1d7..6345f0e618 100644 --- a/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs +++ b/src/ServiceControl.Transports.Tests/TransportManifestLibraryTests.cs @@ -20,7 +20,7 @@ public class TransportManifestLibraryTests [SetUp] public void SetUp() { - LoggerUtil.LoggerFactory = new TestContextAppenderFactory(); + LoggerUtil.ActiveLoggers = Loggers.Test; } [Test] diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index 4a769f63bb..ce312b76f6 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -13,6 +13,7 @@ using NServiceBus.Logging; using NServiceBus.Transport; using NUnit.Framework; + using ServiceControl.Infrastructure.TestLogger; using Transports; [TestFixture] From a843701c7fd7851c85bcce61d633291d6605d752 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Tue, 17 Jun 2025 15:56:17 +0800 Subject: [PATCH 16/27] add ability to select logging provider from config --- src/ServiceControl.Audit/App.config | 3 +++ .../LoggingSettings.cs | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/ServiceControl.Audit/App.config b/src/ServiceControl.Audit/App.config index 00a70ad0a2..e8e4a84c26 100644 --- a/src/ServiceControl.Audit/App.config +++ b/src/ServiceControl.Audit/App.config @@ -21,6 +21,9 @@ These settings are only here so that we can debug ServiceControl while developin + + + diff --git a/src/ServiceControl.Infrastructure/LoggingSettings.cs b/src/ServiceControl.Infrastructure/LoggingSettings.cs index dd9fc18008..a005b64425 100644 --- a/src/ServiceControl.Infrastructure/LoggingSettings.cs +++ b/src/ServiceControl.Infrastructure/LoggingSettings.cs @@ -3,14 +3,33 @@ namespace ServiceControl.Infrastructure; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Extensions.Logging; using ServiceControl.Configuration; -public class LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLevel = LogLevel.Information, string logPath = null) +public class LoggingSettings { - public LogLevel LogLevel { get; } = InitializeLogLevel(rootNamespace, defaultLevel); + public LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLevel = LogLevel.Information, string logPath = null) + { + LogLevel = InitializeLogLevel(rootNamespace, defaultLevel); + LogPath = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); + + var loggingProviders = SettingsReader.Read(rootNamespace, loggingProvidersKey).Split(","); + var activeLoggers = Loggers.None; + if (loggingProviders.Contains("NLog")) + { + activeLoggers |= Loggers.NLog; + } + if (loggingProviders.Contains("Seq")) + { + activeLoggers |= Loggers.Seq; + } + LoggerUtil.ActiveLoggers = activeLoggers; + } + + public LogLevel LogLevel { get; } - public string LogPath { get; } = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); + public string LogPath { get; } static LogLevel InitializeLogLevel(SettingsRootNamespace rootNamespace, LogLevel defaultLevel) { @@ -57,4 +76,5 @@ static LogLevel ParseLogLevel(string value, LogLevel defaultLevel) const string logLevelKey = "LogLevel"; const string logPathKey = "LogPath"; + const string loggingProvidersKey = "LoggingProviders"; } \ No newline at end of file From 3e598862045512ad7d614f847d94508185752826 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Wed, 18 Jun 2025 07:04:03 +0800 Subject: [PATCH 17/27] handle setting not existing --- src/ServiceControl.Infrastructure/LoggingSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ServiceControl.Infrastructure/LoggingSettings.cs b/src/ServiceControl.Infrastructure/LoggingSettings.cs index a005b64425..1a80ccb875 100644 --- a/src/ServiceControl.Infrastructure/LoggingSettings.cs +++ b/src/ServiceControl.Infrastructure/LoggingSettings.cs @@ -14,7 +14,7 @@ public LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLeve LogLevel = InitializeLogLevel(rootNamespace, defaultLevel); LogPath = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); - var loggingProviders = SettingsReader.Read(rootNamespace, loggingProvidersKey).Split(","); + var loggingProviders = (SettingsReader.Read(rootNamespace, loggingProvidersKey) ?? "").Split(","); var activeLoggers = Loggers.None; if (loggingProviders.Contains("NLog")) { From ab580f69fc4288ec013855dbda990417967a88ed Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Wed, 18 Jun 2025 07:53:24 +0800 Subject: [PATCH 18/27] change logmanager logger factory to the standard one now used by the rest of SC --- src/ServiceControl.Infrastructure/LoggingConfigurator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs index 5ca1c06c9b..4845965394 100644 --- a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs +++ b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs @@ -2,15 +2,15 @@ namespace ServiceControl.Infrastructure { using System; using System.IO; + using Microsoft.Extensions.Logging; using NLog; using NLog.Config; - using NLog.Extensions.Logging; using NLog.Layouts; using NLog.Targets; using NServiceBus.Extensions.Logging; using ServiceControl.Configuration; - using LogManager = NServiceBus.Logging.LogManager; + using LogLevel = NLog.LogLevel; // TODO: Migrate from NLog to .NET logging public static class LoggingConfigurator @@ -76,7 +76,7 @@ public static void ConfigureLogging(LoggingSettings loggingSettings) NLog.LogManager.Configuration = nlogConfig; - LogManager.UseFactory(new ExtensionsLoggerFactory(new NLogLoggerFactory())); + LogManager.UseFactory(new ExtensionsLoggerFactory(LoggerFactory.Create(configure => configure.BuildLogger(loggingSettings.LogLevel)))); var logger = LogManager.GetLogger("LoggingConfiguration"); var logEventInfo = new LogEventInfo { TimeStamp = DateTime.UtcNow }; From 3e169708ad450c3c6a768bf433a372cf3e8303ef Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Wed, 18 Jun 2025 13:03:14 +0800 Subject: [PATCH 19/27] ensure logger for transport tests --- src/ServiceControl.Transports.Tests/TransportTestFixture.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index ce312b76f6..ac1501232b 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -13,6 +13,7 @@ using NServiceBus.Logging; using NServiceBus.Transport; using NUnit.Framework; + using ServiceControl.Infrastructure; using ServiceControl.Infrastructure.TestLogger; using Transports; @@ -24,6 +25,7 @@ public virtual async Task Setup() { //TODO remove LogManager usage LogManager.UseFactory(new ExtensionsLoggerFactory(new TestContextAppenderFactory())); + LoggerUtil.ActiveLoggers = Loggers.Test; configuration = new TransportTestsConfiguration(); testCancellationTokenSource = Debugger.IsAttached ? new CancellationTokenSource() : new CancellationTokenSource(TestTimeout); registrations = []; From c92f803edfa45d46d6bc8ed6d0eb73441baa457a Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Wed, 18 Jun 2025 14:12:15 +0800 Subject: [PATCH 20/27] domain events and persister loggers --- .../DiscardMessagesBehavior.cs | 12 +++++++--- .../RavenPersistenceConfiguration.cs | 2 +- .../DomainEvents.cs | 13 ++++------- .../ServiceControl.DomainEvents.csproj | 1 + .../RavenDbLogLevelToLogsModeMapper.cs | 3 ++- .../RepeatedFailuresOverTimeCircuitBreaker.cs | 23 +++++++++---------- .../ExternalIntegrationRequestsDataStore.cs | 21 +++++++++-------- .../RavenPersistenceConfiguration.cs | 3 ++- ...atedFailuresOverTimeCircuitBreakerTests.cs | 13 +++++++++++ 9 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/ServiceControl.AcceptanceTesting/DiscardMessagesBehavior.cs b/src/ServiceControl.AcceptanceTesting/DiscardMessagesBehavior.cs index ed2fd50768..134db9bdec 100644 --- a/src/ServiceControl.AcceptanceTesting/DiscardMessagesBehavior.cs +++ b/src/ServiceControl.AcceptanceTesting/DiscardMessagesBehavior.cs @@ -3,10 +3,11 @@ namespace ServiceControl.AcceptanceTesting using System; using System.Linq; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.AcceptanceTesting; - using NServiceBus.Logging; using NServiceBus.Pipeline; + using ServiceControl.Infrastructure; public class DiscardMessagesBehavior : IBehavior { @@ -44,7 +45,13 @@ public Task Invoke(ITransportReceiveContext context, Func(); + logger.LogDebug("Discarding message '{MessageId}'({OriginalMessageId}) because it's session id is '{MessageSessionId}' instead of '{CurrentSessionId}' Message Types: {EnclosedMessageTypes}.", + context.Message.MessageId, + originalMessageId ?? string.Empty, + session, + currentSession, + enclosedMessageTypes); return Task.CompletedTask; } @@ -52,7 +59,6 @@ public Task Invoke(ITransportReceiveContext context, Func(); static string[] pluginMessages = { diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs index 3611a3f646..eced9e35b2 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenPersistenceConfiguration.cs @@ -108,7 +108,7 @@ internal static DatabaseConfiguration GetDatabaseConfiguration(PersistenceSettin if (settings.PersisterSpecificSettings.TryGetValue(RavenDbLogLevelKey, out var ravenDbLogLevel)) { - logsMode = RavenDbLogLevelToLogsModeMapper.Map(ravenDbLogLevel); + logsMode = RavenDbLogLevelToLogsModeMapper.Map(ravenDbLogLevel, Logger); } serverConfiguration = new ServerConfiguration(dbPath, serverUrl, logPath, logsMode); diff --git a/src/ServiceControl.DomainEvents/DomainEvents.cs b/src/ServiceControl.DomainEvents/DomainEvents.cs index 5443c784d7..0367f199fb 100644 --- a/src/ServiceControl.DomainEvents/DomainEvents.cs +++ b/src/ServiceControl.DomainEvents/DomainEvents.cs @@ -4,15 +4,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; - public class DomainEvents : IDomainEvents + public class DomainEvents(IServiceProvider serviceProvider, ILogger logger) : IDomainEvents { - static readonly ILog Log = LogManager.GetLogger(); - - readonly IServiceProvider serviceProvider; - public DomainEvents(IServiceProvider serviceProvider) => this.serviceProvider = serviceProvider; - public async Task Raise(T domainEvent, CancellationToken cancellationToken) where T : IDomainEvent { var handlers = serviceProvider.GetServices>(); @@ -25,7 +20,7 @@ await handler.Handle(domainEvent, cancellationToken) } catch (Exception e) { - Log.Error($"Unexpected error publishing domain event {typeof(T)}", e); + logger.LogError(e, "Unexpected error publishing domain event {EventType}", typeof(T)); throw; } } @@ -40,7 +35,7 @@ await handler.Handle(domainEvent, cancellationToken) } catch (Exception e) { - Log.Error($"Unexpected error publishing domain event {typeof(T)}", e); + logger.LogError(e, "Unexpected error publishing domain event {EventType}", typeof(T)); throw; } } diff --git a/src/ServiceControl.DomainEvents/ServiceControl.DomainEvents.csproj b/src/ServiceControl.DomainEvents/ServiceControl.DomainEvents.csproj index 8b8037bc48..bb654606ec 100644 --- a/src/ServiceControl.DomainEvents/ServiceControl.DomainEvents.csproj +++ b/src/ServiceControl.DomainEvents/ServiceControl.DomainEvents.csproj @@ -6,6 +6,7 @@ + diff --git a/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs b/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs index 8711bc9854..16a99ab8f3 100644 --- a/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs +++ b/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs @@ -1,12 +1,13 @@ namespace ServiceControl { + using Microsoft.Extensions.Logging; using NServiceBus.Logging; public class RavenDbLogLevelToLogsModeMapper { static readonly ILog Logger = LogManager.GetLogger(typeof(RavenDbLogLevelToLogsModeMapper)); - public static string Map(string ravenDbLogLevel) + public static string Map(string ravenDbLogLevel, ILogger logger) { switch (ravenDbLogLevel.ToLower()) { diff --git a/src/ServiceControl.Infrastructure/RepeatedFailuresOverTimeCircuitBreaker.cs b/src/ServiceControl.Infrastructure/RepeatedFailuresOverTimeCircuitBreaker.cs index abd6c9a354..3ae3d1c879 100644 --- a/src/ServiceControl.Infrastructure/RepeatedFailuresOverTimeCircuitBreaker.cs +++ b/src/ServiceControl.Infrastructure/RepeatedFailuresOverTimeCircuitBreaker.cs @@ -5,7 +5,7 @@ namespace NServiceBus; using System; using System.Threading; using System.Threading.Tasks; -using Logging; +using Microsoft.Extensions.Logging; /// /// A circuit breaker that is armed on a failure and disarmed on success. After in the @@ -44,6 +44,7 @@ public RepeatedFailuresOverTimeCircuitBreaker( string name, TimeSpan timeToWaitBeforeTriggering, Action triggerAction, + ILogger logger, Action? armedAction = null, Action? disarmedAction = null, TimeSpan? timeToWaitWhenTriggered = default, @@ -51,6 +52,7 @@ public RepeatedFailuresOverTimeCircuitBreaker( { this.name = name; this.triggerAction = triggerAction; + this.logger = logger; this.armedAction = armedAction ?? (static () => { }); this.disarmedAction = disarmedAction ?? (static () => { }); this.timeToWaitBeforeTriggering = timeToWaitBeforeTriggering; @@ -82,14 +84,14 @@ public void Success() circuitBreakerState = Disarmed; _ = timer.Change(Timeout.Infinite, Timeout.Infinite); - Logger.InfoFormat("The circuit breaker for '{0}' is now disarmed.", name); + logger.LogInformation("The circuit breaker for '{BreakerName}' is now disarmed.", name); try { disarmedAction(); } catch (Exception ex) { - Logger.Error($"The circuit breaker for '{name}' was unable to execute the disarm action.", ex); + logger.LogError(ex, "The circuit breaker for '{BreakerName}' was unable to execute the disarm action.", name); throw; } } @@ -130,12 +132,12 @@ public Task Failure(Exception exception, CancellationToken cancellationToken = d } catch (Exception ex) { - Logger.Error($"The circuit breaker for '{name}' was unable to execute the arm action.", new AggregateException(ex, exception)); + logger.LogError(new AggregateException(ex, exception), "The circuit breaker for '{BreakerName}' was unable to execute the arm action.", name); throw; } _ = timer.Change(timeToWaitBeforeTriggering, NoPeriodicTriggering); - Logger.WarnFormat("The circuit breaker for '{0}' is now in the armed state due to '{1}' and might trigger in '{2}' when not disarmed.", name, exception, timeToWaitBeforeTriggering); + logger.LogWarning("The circuit breaker for '{BreakerName}' is now in the armed state due to '{BreakerCause}' and might trigger in '{BreakerTriggerTime}' when not disarmed.", name, exception, timeToWaitBeforeTriggering); } return Delay(); @@ -143,10 +145,7 @@ public Task Failure(Exception exception, CancellationToken cancellationToken = d Task Delay() { var timeToWait = previousState == Triggered ? timeToWaitWhenTriggered : timeToWaitWhenArmed; - if (Logger.IsDebugEnabled) - { - Logger.DebugFormat("The circuit breaker for '{0}' is delaying the operation by '{1}'.", name, timeToWait); - } + logger.LogDebug("The circuit breaker for '{BreakerName}' is delaying the operation by '{BreakerTriggerTime}'.", name, timeToWait); return Task.Delay(timeToWait, cancellationToken); } } @@ -173,7 +172,7 @@ void CircuitBreakerTriggered(object? state) } circuitBreakerState = Triggered; - Logger.WarnFormat("The circuit breaker for '{0}' will now be triggered with exception '{1}'.", name, lastException); + logger.LogWarning("The circuit breaker for '{BreakerName}' will now be triggered with exception '{BreakerCause}'.", name, lastException); try { @@ -181,7 +180,7 @@ void CircuitBreakerTriggered(object? state) } catch (Exception ex) { - Logger.Fatal($"The circuit breaker for '{name}' was unable to execute the trigger action.", new AggregateException(ex, lastException!)); + logger.LogCritical(new AggregateException(ex, lastException!), "The circuit breaker for '{BreakerName}' was unable to execute the trigger action.", name); } } } @@ -204,5 +203,5 @@ void CircuitBreakerTriggered(object? state) const int Triggered = 2; static readonly TimeSpan NoPeriodicTriggering = TimeSpan.FromMilliseconds(-1); - static readonly ILog Logger = LogManager.GetLogger(); + readonly ILogger logger; } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/ExternalIntegrationRequestsDataStore.cs b/src/ServiceControl.Persistence.RavenDB/ExternalIntegrationRequestsDataStore.cs index 27762fc546..6f68141edc 100644 --- a/src/ServiceControl.Persistence.RavenDB/ExternalIntegrationRequestsDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/ExternalIntegrationRequestsDataStore.cs @@ -8,8 +8,8 @@ using System.Threading.Tasks; using ExternalIntegrations; using Microsoft.Extensions.Hosting; + using Microsoft.Extensions.Logging; using NServiceBus; - using NServiceBus.Logging; using Raven.Client.Documents; using Raven.Client.Documents.Changes; using ServiceControl.Infrastructure; @@ -20,12 +20,17 @@ class ExternalIntegrationRequestsDataStore , IAsyncDisposable { - public ExternalIntegrationRequestsDataStore(RavenPersisterSettings settings, IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, CriticalError criticalError) + public ExternalIntegrationRequestsDataStore( + RavenPersisterSettings settings, + IRavenSessionProvider sessionProvider, + IRavenDocumentStoreProvider documentStoreProvider, + CriticalError criticalError, + ILogger logger) { this.settings = settings; this.sessionProvider = sessionProvider; this.documentStoreProvider = documentStoreProvider; - + this.logger = logger; var timeToWait = TimeSpan.FromMinutes(5); var delayAfterFailure = TimeSpan.FromSeconds(20); @@ -33,6 +38,7 @@ public ExternalIntegrationRequestsDataStore(RavenPersisterSettings settings, IRa "EventDispatcher", timeToWait, ex => criticalError.Raise("Repeated failures when dispatching external integration events.", ex), + logger, timeToWaitWhenArmed: delayAfterFailure ); } @@ -97,7 +103,7 @@ async Task StartDispatcherTask(CancellationToken cancellationToken) } catch (Exception ex) { - Logger.Error("An exception occurred when dispatching external integration events", ex); + logger.LogError(ex, "An exception occurred when dispatching external integration events"); await circuitBreaker.Failure(ex, cancellationToken); if (!tokenSource.IsCancellationRequested) @@ -143,10 +149,7 @@ async Task TryDispatchEventBatch() } var allContexts = awaitingDispatching.Select(r => r.DispatchContext).ToArray(); - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Dispatching {allContexts.Length} events."); - } + logger.LogDebug("Dispatching {EventCount} events.", allContexts.Length); await callback(allContexts); @@ -206,6 +209,6 @@ public async ValueTask DisposeAsync() Func callback; bool isDisposed; - static ILog Logger = LogManager.GetLogger(typeof(ExternalIntegrationRequestsDataStore)); + readonly ILogger logger; } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/RavenPersistenceConfiguration.cs b/src/ServiceControl.Persistence.RavenDB/RavenPersistenceConfiguration.cs index f9f66aa6ca..c9d03685e7 100644 --- a/src/ServiceControl.Persistence.RavenDB/RavenPersistenceConfiguration.cs +++ b/src/ServiceControl.Persistence.RavenDB/RavenPersistenceConfiguration.cs @@ -6,6 +6,7 @@ using Configuration; using CustomChecks; using Particular.LicensingComponent.Contracts; + using ServiceControl.Infrastructure; class RavenPersistenceConfiguration : IPersistenceConfiguration { @@ -29,7 +30,7 @@ static T GetRequiredSetting(SettingsRootNamespace settingsRootNamespace, stri } var ravenDbLogLevel = SettingsReader.Read(settingsRootNamespace, RavenBootstrapper.RavenDbLogLevelKey, "Warn"); - var logsMode = RavenDbLogLevelToLogsModeMapper.Map(ravenDbLogLevel); + var logsMode = RavenDbLogLevelToLogsModeMapper.Map(ravenDbLogLevel, LoggerUtil.CreateStaticLogger()); var settings = new RavenPersisterSettings { diff --git a/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs b/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs index 67e71198cc..e955646a88 100644 --- a/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs +++ b/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs @@ -6,12 +6,16 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; + using ServiceControl.Infrastructure; // Ideally the circuit breaker would use a time provider to allow for easier testing but that would require a significant refactor // and we want keep the changes to a minimum for now to allow backporting to older versions. [TestFixture] public class RepeatedFailuresOverTimeCircuitBreakerTests { + [SetUp] + public void Setup() => LoggerUtil.ActiveLoggers = Loggers.Test; + [Test] public async Task Should_disarm_on_success() { @@ -22,6 +26,7 @@ public async Task Should_disarm_on_success() "TestCircuitBreaker", TimeSpan.FromMilliseconds(100), ex => { }, + LoggerUtil.CreateStaticLogger(), () => armedActionCalled = true, () => disarmedActionCalled = true, TimeSpan.Zero, @@ -42,6 +47,7 @@ public async Task Should_rethrow_exception_on_success() "TestCircuitBreaker", TimeSpan.FromMilliseconds(100), ex => { }, + LoggerUtil.CreateStaticLogger(), () => { }, () => throw new Exception("Exception from disarmed action"), timeToWaitWhenTriggered: TimeSpan.Zero, @@ -64,6 +70,7 @@ public async Task Should_trigger_after_failure_timeout() "TestCircuitBreaker", TimeSpan.Zero, ex => { triggerActionCalled = true; lastTriggerException = ex; }, + LoggerUtil.CreateStaticLogger(), timeToWaitWhenTriggered: TimeSpan.Zero, timeToWaitWhenArmed: TimeSpan.FromMilliseconds(100) ); @@ -81,6 +88,7 @@ public void Should_rethrow_exception_on_failure() "TestCircuitBreaker", TimeSpan.FromMilliseconds(100), ex => { }, + LoggerUtil.CreateStaticLogger(), () => throw new Exception("Exception from armed action"), () => { }, timeToWaitWhenTriggered: TimeSpan.Zero, @@ -101,6 +109,7 @@ public async Task Should_delay_after_trigger_failure() "TestCircuitBreaker", TimeSpan.Zero, _ => { }, + LoggerUtil.CreateStaticLogger(), timeToWaitWhenTriggered: timeToWaitWhenTriggered, timeToWaitWhenArmed: timeToWaitWhenArmed ); @@ -124,6 +133,7 @@ public async Task Should_not_trigger_if_disarmed_before_timeout() "TestCircuitBreaker", TimeSpan.FromMilliseconds(100), ex => triggerActionCalled = true, + LoggerUtil.CreateStaticLogger(), timeToWaitWhenTriggered: TimeSpan.Zero, timeToWaitWhenArmed: TimeSpan.Zero ); @@ -145,6 +155,7 @@ public async Task Should_handle_concurrent_failure_and_success() "TestCircuitBreaker", TimeSpan.FromMilliseconds(100), ex => triggerActionCalled = true, + LoggerUtil.CreateStaticLogger(), () => armedActionCalled = true, () => disarmedActionCalled = true, TimeSpan.Zero, @@ -176,6 +187,7 @@ public async Task Should_handle_high_concurrent_failure_and_success() "TestCircuitBreaker", TimeSpan.FromSeconds(5), ex => Interlocked.Increment(ref triggerActionCalled), + LoggerUtil.CreateStaticLogger(), () => Interlocked.Increment(ref armedActionCalled), () => Interlocked.Increment(ref disarmedActionCalled), TimeSpan.Zero, @@ -209,6 +221,7 @@ public async Task Should_trigger_after_multiple_failures_and_timeout() "TestCircuitBreaker", TimeSpan.FromMilliseconds(50), ex => triggerActionCalled = true, + LoggerUtil.CreateStaticLogger(), timeToWaitWhenTriggered: TimeSpan.FromMilliseconds(50), timeToWaitWhenArmed: TimeSpan.FromMilliseconds(50) ); From 479d40936103f9a8bec6b5b537ff00edda6daf6a Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Thu, 19 Jun 2025 08:43:16 +0800 Subject: [PATCH 21/27] set default to nlog and pass loglevel to test context --- src/ServiceControl.Infrastructure/LoggerUtil.cs | 2 +- src/ServiceControl.Infrastructure/LoggingSettings.cs | 3 ++- .../TestLogger/TestContextAppender.cs | 4 ++-- .../TestLogger/TestContextAppenderFactory.cs | 4 ++-- .../TestLogger/TestContextProvider.cs | 9 ++++++++- .../ServiceControl.Persistence.Tests.InMemory.csproj | 1 + .../ServiceControl.Persistence.Tests.RavenDB.csproj | 1 + .../PersistenceTestBase.cs | 6 ++++++ src/ServiceControl.RavenDB/ServiceControl.RavenDB.csproj | 4 ++++ .../TransportTestFixture.cs | 2 +- 10 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index 34fc16beb1..f85bd6776a 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -23,7 +23,7 @@ public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel lev { if ((Loggers.Test & ActiveLoggers) == Loggers.Test) { - loggingBuilder.Services.AddSingleton(new TestContextProvider()); + loggingBuilder.Services.AddSingleton(new TestContextProvider(level)); } if ((Loggers.NLog & ActiveLoggers) == Loggers.NLog) { diff --git a/src/ServiceControl.Infrastructure/LoggingSettings.cs b/src/ServiceControl.Infrastructure/LoggingSettings.cs index 1a80ccb875..c48b27d889 100644 --- a/src/ServiceControl.Infrastructure/LoggingSettings.cs +++ b/src/ServiceControl.Infrastructure/LoggingSettings.cs @@ -24,7 +24,8 @@ public LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLeve { activeLoggers |= Loggers.Seq; } - LoggerUtil.ActiveLoggers = activeLoggers; + //this defaults to NLog because historically that was the default, and we don't want to break existing installs that don't have the config key to define loggingProviders + LoggerUtil.ActiveLoggers = activeLoggers == Loggers.None ? Loggers.NLog : activeLoggers; } public LogLevel LogLevel { get; } diff --git a/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs index c353a3b60a..ed37368e16 100644 --- a/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppender.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging; using NUnit.Framework; - class TestContextAppender(string categoryName) : ILogger + class TestContextAppender(string categoryName, LogLevel level) : ILogger { public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { @@ -13,7 +13,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except TestContext.Out.WriteLine($"{categoryName}: {formatter(state, exception)}"); } } - public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning; + public bool IsEnabled(LogLevel logLevel) => logLevel >= level; public IDisposable BeginScope(TState state) where TState : notnull => Disposable.Instance; diff --git a/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs index 98e1d683fb..3cac38fce7 100644 --- a/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextAppenderFactory.cs @@ -2,13 +2,13 @@ { using Microsoft.Extensions.Logging; - public class TestContextAppenderFactory : ILoggerFactory + public class TestContextAppenderFactory(LogLevel logLevel) : ILoggerFactory { public void AddProvider(ILoggerProvider provider) { } - public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName); + public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName, logLevel); public void Dispose() { diff --git a/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs b/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs index e879c814a3..90e2dae5d8 100644 --- a/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs +++ b/src/ServiceControl.Infrastructure/TestLogger/TestContextProvider.cs @@ -4,7 +4,14 @@ public class TestContextProvider : ILoggerProvider { - public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName); + readonly LogLevel level; + + public TestContextProvider(LogLevel level) + { + this.level = level; + } + + public ILogger CreateLogger(string categoryName) => new TestContextAppender(categoryName, level); public void Dispose() { diff --git a/src/ServiceControl.Persistence.Tests.InMemory/ServiceControl.Persistence.Tests.InMemory.csproj b/src/ServiceControl.Persistence.Tests.InMemory/ServiceControl.Persistence.Tests.InMemory.csproj index 4e0fac1da4..14f8701c33 100644 --- a/src/ServiceControl.Persistence.Tests.InMemory/ServiceControl.Persistence.Tests.InMemory.csproj +++ b/src/ServiceControl.Persistence.Tests.InMemory/ServiceControl.Persistence.Tests.InMemory.csproj @@ -6,6 +6,7 @@ + diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/ServiceControl.Persistence.Tests.RavenDB.csproj b/src/ServiceControl.Persistence.Tests.RavenDB/ServiceControl.Persistence.Tests.RavenDB.csproj index bb4f028ee1..f3ed716dde 100644 --- a/src/ServiceControl.Persistence.Tests.RavenDB/ServiceControl.Persistence.Tests.RavenDB.csproj +++ b/src/ServiceControl.Persistence.Tests.RavenDB/ServiceControl.Persistence.Tests.RavenDB.csproj @@ -5,6 +5,7 @@ + diff --git a/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs b/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs index c6d0de3aa2..7cc5f39cca 100644 --- a/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs +++ b/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs @@ -4,10 +4,12 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Settings; using NUnit.Framework; using Particular.LicensingComponent.Persistence; +using ServiceControl.Infrastructure; using ServiceControl.Infrastructure.DomainEvents; using ServiceControl.Operations.BodyStorage; using ServiceControl.Persistence; @@ -30,6 +32,10 @@ public async Task SetUp() } var hostBuilder = Host.CreateApplicationBuilder(); + + LoggerUtil.ActiveLoggers = Loggers.Test; + hostBuilder.Logging.BuildLogger(LogLevel.Information); + await PersistenceTestsContext.Setup(hostBuilder); // This is not cool. We have things that are registered as part of "the persistence" that then require parts diff --git a/src/ServiceControl.RavenDB/ServiceControl.RavenDB.csproj b/src/ServiceControl.RavenDB/ServiceControl.RavenDB.csproj index 46705a80e7..0479c4ff74 100644 --- a/src/ServiceControl.RavenDB/ServiceControl.RavenDB.csproj +++ b/src/ServiceControl.RavenDB/ServiceControl.RavenDB.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index ac1501232b..9ecf8f1725 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -24,7 +24,7 @@ class TransportTestFixture public virtual async Task Setup() { //TODO remove LogManager usage - LogManager.UseFactory(new ExtensionsLoggerFactory(new TestContextAppenderFactory())); + LogManager.UseFactory(new ExtensionsLoggerFactory(new TestContextAppenderFactory(Microsoft.Extensions.Logging.LogLevel.Warning))); LoggerUtil.ActiveLoggers = Loggers.Test; configuration = new TransportTestsConfiguration(); testCancellationTokenSource = Debugger.IsAttached ? new CancellationTokenSource() : new CancellationTokenSource(TestTimeout); From 316516e521b5053c08c575ff51a7889968180f7e Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Thu, 19 Jun 2025 12:04:24 +0800 Subject: [PATCH 22/27] replace logmanager usage in persistence --- .../CustomChecks/CheckDirtyMemory.cs | 13 ++--- .../CustomChecks/CheckFreeDiskSpace.cs | 29 ++++------- ...CheckMinimumStorageRequiredForIngestion.cs | 38 +++++++------- .../CustomChecks/CheckRavenDBIndexErrors.cs | 8 ++- .../CustomChecks/CheckRavenDBIndexLag.cs | 17 +++---- .../ErrorMessagesDataStore.cs | 13 +++-- .../FailedErrorImportDataStore.cs | 19 +++---- .../FailedMessageViewIndexNotifications.cs | 8 ++- .../Subscriptions/RavenSubscriptionStorage.cs | 18 +++---- .../RavenEmbeddedPersistenceLifecycle.cs | 8 ++- .../Archiving/ArchiveDocumentManager.cs | 7 ++- .../Archiving/MessageArchiver.cs | 51 ++++++++++--------- .../RetryBatchesDataStore.cs | 14 +++-- .../RetryDocumentDataStore.cs | 8 ++- .../SubscriptionPersisterTests.cs | 5 +- .../PersistenceManifest.cs | 10 ++-- .../EmbeddedDatabase.cs | 33 ++++++------ 17 files changed, 135 insertions(+), 164 deletions(-) diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs index 8eee53911a..c90bbc4a8e 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckDirtyMemory.cs @@ -3,26 +3,23 @@ namespace ServiceControl.Persistence.RavenDB.CustomChecks; using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; -using NServiceBus.Logging; -class CheckDirtyMemory(MemoryInformationRetriever memoryInformationRetriever) : CustomCheck("RavenDB dirty memory", "ServiceControl Health", TimeSpan.FromMinutes(5)) +class CheckDirtyMemory(MemoryInformationRetriever memoryInformationRetriever, ILogger logger) : CustomCheck("RavenDB dirty memory", "ServiceControl Health", TimeSpan.FromMinutes(5)) { public override async Task PerformCheck(CancellationToken cancellationToken = default) { var (isHighDirty, dirtyMemory) = await memoryInformationRetriever.GetMemoryInformation(cancellationToken); - Log.Debug($"RavenDB dirty memory value: {dirtyMemory}."); + logger.LogDebug("RavenDB dirty memory value: {DirtyMemory}.", dirtyMemory); if (isHighDirty) { - var message = $"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue."; - Log.Warn(message); - return CheckResult.Failed(message); + logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.", dirtyMemory); + return CheckResult.Failed($"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue."); } return CheckResult.Pass; } - - static readonly ILog Log = LogManager.GetLogger(); } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs index c90bce9807..22029f309c 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckFreeDiskSpace.cs @@ -4,18 +4,16 @@ using System.IO; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; + using ServiceControl.Infrastructure; using ServiceControl.Persistence.RavenDB; - class CheckFreeDiskSpace(RavenPersisterSettings settings) : CustomCheck("ServiceControl database", "Storage space", TimeSpan.FromMinutes(5)) + class CheckFreeDiskSpace(RavenPersisterSettings settings, ILogger logger) : CustomCheck("ServiceControl database", "Storage space", TimeSpan.FromMinutes(5)) { public override Task PerformCheck(CancellationToken cancellationToken = default) { - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Check ServiceControl data drive space remaining custom check starting. Threshold {percentageThreshold:P0}"); - } + logger.LogDebug("Check ServiceControl data drive space remaining custom check starting. Threshold {PercentageThreshold:P0}", percentageThreshold); if (!settings.UseEmbeddedServer) { @@ -33,10 +31,7 @@ public override Task PerformCheck(CancellationToken cancellationTok var percentRemaining = (decimal)dataDriveInfo.AvailableFreeSpace / dataDriveInfo.TotalSize; - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Free space: {availableFreeSpace:N0}B | Total: {totalSpace:N0}B | Percent remaining {percentRemaining:P1}"); - } + logger.LogDebug("Free space: {AvailableFreeSpace:N0}B | Total: {TotalSpace:N0}B | Percent remaining {PercentRemaining:P1}", availableFreeSpace, totalSpace, percentRemaining); return percentRemaining > percentageThreshold ? CheckResult.Pass @@ -45,22 +40,19 @@ public override Task PerformCheck(CancellationToken cancellationTok public static void Validate(RavenPersisterSettings settings) { + var logger = LoggerUtil.CreateStaticLogger(); var threshold = settings.DataSpaceRemainingThreshold; - string message; - if (threshold < 0) { - message = $"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, minimum value is 0."; - Logger.Fatal(message); - throw new Exception(message); + logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, minimum value is 0.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, minimum value is 0."); } if (threshold > 100) { - message = $"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, maximum value is 100."; - Logger.Fatal(message); - throw new Exception(message); + logger.LogCritical("{RavenPersistenceConfigurationDataSpaceRemainingThresholdKey} is invalid, maximum value is 100.", RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey); + throw new Exception($"{RavenPersistenceConfiguration.DataSpaceRemainingThresholdKey} is invalid, maximum value is 100."); } } @@ -68,6 +60,5 @@ public static void Validate(RavenPersisterSettings settings) readonly decimal percentageThreshold = settings.DataSpaceRemainingThreshold / 100m; public const int DataSpaceRemainingThresholdDefault = 20; - static readonly ILog Logger = LogManager.GetLogger(typeof(CheckFreeDiskSpace)); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs index 053a41cff7..0c04857571 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckMinimumStorageRequiredForIngestion.cs @@ -4,21 +4,19 @@ using System.IO; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; + using ServiceControl.Infrastructure; using ServiceControl.Persistence; using ServiceControl.Persistence.RavenDB; - class CheckMinimumStorageRequiredForIngestion(MinimumRequiredStorageState stateHolder, RavenPersisterSettings settings) : CustomCheck("Message Ingestion Process", "ServiceControl Health", TimeSpan.FromSeconds(5)) + class CheckMinimumStorageRequiredForIngestion(MinimumRequiredStorageState stateHolder, RavenPersisterSettings settings, ILogger logger) : CustomCheck("Message Ingestion Process", "ServiceControl Health", TimeSpan.FromSeconds(5)) { public override Task PerformCheck(CancellationToken cancellationToken = default) { var percentageThreshold = settings.MinimumStorageLeftRequiredForIngestion / 100m; - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Check ServiceControl data drive space starting. Threshold {percentageThreshold:P0}"); - } + logger.LogDebug("Check ServiceControl data drive space starting. Threshold {PercentageThreshold:P0}", percentageThreshold); // Should be checking UseEmbeddedServer but need to check DatabasePath instead for the ATT hack to work if (string.IsNullOrEmpty(settings.DatabasePath)) @@ -35,10 +33,7 @@ public override Task PerformCheck(CancellationToken cancellationTok var percentRemaining = (decimal)dataDriveInfo.AvailableFreeSpace / dataDriveInfo.TotalSize; - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Free space: {availableFreeSpace:N0}B | Total: {totalSpace:N0}B | Percent remaining {percentRemaining:P1}"); - } + logger.LogDebug("Free space: {AvailableFreeSpace:N0}B | Total: {TotalSpace:N0}B | Percent remaining {PercentRemaining:P1}", availableFreeSpace, totalSpace, percentRemaining); if (percentRemaining > percentageThreshold) { @@ -46,33 +41,36 @@ public override Task PerformCheck(CancellationToken cancellationTok return SuccessResult; } - var message = $"Error message ingestion stopped! {percentRemaining:P0} disk space remaining on data drive '{dataDriveInfo.VolumeLabel} ({dataDriveInfo.RootDirectory})' on '{Environment.MachineName}'. This is less than {percentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} configuration setting."; - Logger.Warn(message); + logger.LogWarning("Error message ingestion stopped! {PercentRemaining:P0} disk space remaining on data drive '{DataDriveInfoVolumeLabel} ({DataDriveInfoRootDirectory})' on '{MachineName}'. This is less than {PercentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenBootstrapperMinimumStorageLeftRequiredForIngestionKey} configuration setting.", + percentRemaining, + dataDriveInfo.VolumeLabel, + dataDriveInfo.RootDirectory, + Environment.MachineName, + percentageThreshold, + RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey); stateHolder.CanIngestMore = false; - return CheckResult.Failed(message); + return CheckResult.Failed($"Error message ingestion stopped! {percentRemaining:P0} disk space remaining on data drive '{dataDriveInfo.VolumeLabel} ({dataDriveInfo.RootDirectory})' on '{Environment.MachineName}'. This is less than {percentageThreshold}% - the minimal required space configured. The threshold can be set using the {RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} configuration setting."); } public static void Validate(RavenPersisterSettings settings) { + var logger = LoggerUtil.CreateStaticLogger(); var threshold = settings.MinimumStorageLeftRequiredForIngestion; if (threshold < 0) { - var message = $"{RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0."; - Logger.Fatal(message); - throw new Exception(message); + logger.LogCritical("{RavenBootstrapperMinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0.", RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey); + throw new Exception($"{RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} is invalid, minimum value is 0."); } if (threshold > 100) { - var message = $"{RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100."; - Logger.Fatal(message); - throw new Exception(message); + logger.LogCritical("{RavenBootstrapperMinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100.", RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey); + throw new Exception($"{RavenBootstrapper.MinimumStorageLeftRequiredForIngestionKey} is invalid, maximum value is 100."); } } public const int MinimumStorageLeftRequiredForIngestionDefault = 5; static readonly Task SuccessResult = Task.FromResult(CheckResult.Pass); - static readonly ILog Logger = LogManager.GetLogger(typeof(CheckMinimumStorageRequiredForIngestion)); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexErrors.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexErrors.cs index 5567aa7507..89ea567a80 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexErrors.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexErrors.cs @@ -5,12 +5,12 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using Raven.Client.Documents.Operations.Indexes; using ServiceControl.Persistence.RavenDB; - class CheckRavenDBIndexErrors(IRavenDocumentStoreProvider documentStoreProvider) : CustomCheck("Error Database Index Errors", "ServiceControl Health", TimeSpan.FromMinutes(5)) + class CheckRavenDBIndexErrors(IRavenDocumentStoreProvider documentStoreProvider, ILogger logger) : CustomCheck("Error Database Index Errors", "ServiceControl Health", TimeSpan.FromMinutes(5)) { public override async Task PerformCheck(CancellationToken cancellationToken = default) { @@ -41,10 +41,8 @@ public override async Task PerformCheck(CancellationToken cancellat text.AppendLine().AppendLine("See: https://docs.particular.net/search?q=servicecontrol+troubleshooting"); var message = text.ToString(); - Logger.Error(message); + logger.LogError(message); return CheckResult.Failed(message); } - - static readonly ILog Logger = LogManager.GetLogger(); } } diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs index 7084d78e34..d0fd05de1c 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs @@ -5,13 +5,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus.CustomChecks; - using NServiceBus.Logging; using Raven.Client.Documents.Operations; using ServiceControl.Persistence.RavenDB; using CustomCheck = NServiceBus.CustomChecks.CustomCheck; - class CheckRavenDBIndexLag(IRavenDocumentStoreProvider documentStoreProvider) : CustomCheck("Error Database Index Lag", "ServiceControl Health", TimeSpan.FromMinutes(5)) + class CheckRavenDBIndexLag(IRavenDocumentStoreProvider documentStoreProvider, ILogger logger) : CustomCheck("Error Database Index Lag", "ServiceControl Health", TimeSpan.FromMinutes(5)) { public override async Task PerformCheck(CancellationToken cancellationToken = default) { @@ -31,7 +31,7 @@ public override async Task PerformCheck(CancellationToken cancellat return CheckResult.Pass; } - static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) + int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) { int indexCountWithTooMuchLag = 0; @@ -44,12 +44,12 @@ static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) if (indexLag > IndexLagThresholdError) { indexCountWithTooMuchLag++; - Log.Error($"Index [{indexStats.Name}] IndexingLag {indexLag} is above error threshold ({IndexLagThresholdError}). Launch in maintenance mode to let indexes catch up."); + logger.LogError("Index [{IndexName}] IndexingLag {IndexLag} is above error threshold ({IndexLagThresholdError}). Launch in maintenance mode to let indexes catch up.", indexStats.Name, indexLag, IndexLagThresholdError); } else if (indexLag > IndexLagThresholdWarning) { indexCountWithTooMuchLag++; - Log.Warn($"Index [{indexStats.Name}] IndexingLag {indexLag} is above warning threshold ({IndexLagThresholdWarning}). Launch in maintenance mode to let indexes catch up."); + logger.LogWarning("Index [{IndexName}] IndexingLag {IndexLag} is above warning threshold ({IndexLagThresholdWarning}). Launch in maintenance mode to let indexes catch up.", indexStats.Name, indexLag, IndexLagThresholdWarning); } } } @@ -57,9 +57,9 @@ static int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) return indexCountWithTooMuchLag; } - static void CreateDiagnosticsLogEntry(DatabaseStatistics statistics, IndexInformation[] indexes) + void CreateDiagnosticsLogEntry(DatabaseStatistics statistics, IndexInformation[] indexes) { - if (!Log.IsDebugEnabled) + if (!logger.IsEnabled(LogLevel.Debug)) { return; } @@ -73,11 +73,10 @@ static void CreateDiagnosticsLogEntry(DatabaseStatistics statistics, IndexInform { report.AppendLine($"- Index [{indexStats.Name,-44}] State: {indexStats.State}, Stale: {indexStats.IsStale,-5}, Priority: {indexStats.Priority,-6}, LastIndexingTime: {indexStats.LastIndexingTime:u}"); } - Log.Debug(report.ToString()); + logger.LogDebug(report.ToString()); } static readonly TimeSpan IndexLagThresholdWarning = TimeSpan.FromMinutes(1); static readonly TimeSpan IndexLagThresholdError = TimeSpan.FromMinutes(10); - static readonly ILog Log = LogManager.GetLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/ErrorMessagesDataStore.cs b/src/ServiceControl.Persistence.RavenDB/ErrorMessagesDataStore.cs index 4c3f77bf6d..4940807646 100644 --- a/src/ServiceControl.Persistence.RavenDB/ErrorMessagesDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/ErrorMessagesDataStore.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Threading.Tasks; using Editing; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client; using Raven.Client.Documents; using Raven.Client.Documents.Commands; @@ -28,7 +28,8 @@ class ErrorMessagesDataStore( IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, IBodyStorage bodyStorage, - ExpirationManager expirationManager) + ExpirationManager expirationManager, + ILogger logger) : IErrorMessageDataStore { public async Task>> GetAllMessages( @@ -338,7 +339,7 @@ public async Task ErrorLastBy(string failedMessageId) return result; } - static FailedMessageView Map(FailedMessage message, IAsyncDocumentSession session) + FailedMessageView Map(FailedMessage message, IAsyncDocumentSession session) { var processingAttempt = message.ProcessingAttempts.Last(); @@ -369,7 +370,7 @@ static FailedMessageView Map(FailedMessage message, IAsyncDocumentSession sessio } catch (Exception ex) { - Logger.Warn($"Unable to parse SendingEndpoint from metadata for messageId {message.UniqueMessageId}", ex); + logger.LogWarning(ex, "Unable to parse SendingEndpoint from metadata for messageId {UniqueMessageId}", message.UniqueMessageId); failedMsgView.SendingEndpoint = EndpointDetailsParser.SendingEndpoint(processingAttempt.Headers); } @@ -379,7 +380,7 @@ static FailedMessageView Map(FailedMessage message, IAsyncDocumentSession sessio } catch (Exception ex) { - Logger.Warn($"Unable to parse ReceivingEndpoint from metadata for messageId {message.UniqueMessageId}", ex); + logger.LogWarning(ex, "Unable to parse ReceivingEndpoint from metadata for messageId {UniqueMessageId}", message.UniqueMessageId); failedMsgView.ReceivingEndpoint = EndpointDetailsParser.ReceivingEndpoint(processingAttempt.Headers); } @@ -676,7 +677,5 @@ public async Task StoreFailedMessagesForTestsOnly(params FailedMessage[] failedM await session.SaveChangesAsync(); } - - static readonly ILog Logger = LogManager.GetLogger(); } } diff --git a/src/ServiceControl.Persistence.RavenDB/FailedErrorImportDataStore.cs b/src/ServiceControl.Persistence.RavenDB/FailedErrorImportDataStore.cs index 440468a790..730413af0b 100644 --- a/src/ServiceControl.Persistence.RavenDB/FailedErrorImportDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/FailedErrorImportDataStore.cs @@ -3,14 +3,12 @@ using System; using System.Threading; using System.Threading.Tasks; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client.Documents.Commands; using ServiceControl.Operations; - class FailedErrorImportDataStore(IRavenSessionProvider sessionProvider) : IFailedErrorImportDataStore + class FailedErrorImportDataStore(IRavenSessionProvider sessionProvider, ILogger logger) : IFailedErrorImportDataStore { - static readonly ILog Logger = LogManager.GetLogger(typeof(FailedErrorImportDataStore)); - public async Task ProcessFailedErrorImports(Func processMessage, CancellationToken cancellationToken) { var succeeded = 0; @@ -30,28 +28,25 @@ public async Task ProcessFailedErrorImports(Func p succeeded++; - if (Logger.IsDebugEnabled) - { - Logger.Debug($"Successfully re-imported failed error message {transportMessage.Id}."); - } + logger.LogDebug("Successfully re-imported failed error message {MessageId}", transportMessage.Id); } catch (OperationCanceledException e) when (cancellationToken.IsCancellationRequested) { - Logger.Info("Cancelled", e); + logger.LogInformation(e, "Cancelled"); } catch (Exception e) { - Logger.Error($"Error while attempting to re-import failed error message {transportMessage.Id}.", e); + logger.LogError(e, "Error while attempting to re-import failed error message {MessageId}.", transportMessage.Id); failed++; } } } - Logger.Info($"Done re-importing failed errors. Successfully re-imported {succeeded} messages. Failed re-importing {failed} messages."); + logger.LogInformation("Done re-importing failed errors. Successfully re-imported {SucceededCount} messages. Failed re-importing {FailedCount} messages.", succeeded, failed); if (failed > 0) { - Logger.Warn($"{failed} messages could not be re-imported. This could indicate a problem with the data. Contact Particular support if you need help with recovering the messages."); + logger.LogWarning("{FailedCount} messages could not be re-imported. This could indicate a problem with the data. Contact Particular support if you need help with recovering the messages.", failed); } } diff --git a/src/ServiceControl.Persistence.RavenDB/FailedMessageViewIndexNotifications.cs b/src/ServiceControl.Persistence.RavenDB/FailedMessageViewIndexNotifications.cs index 690bc056bb..83b2370b36 100644 --- a/src/ServiceControl.Persistence.RavenDB/FailedMessageViewIndexNotifications.cs +++ b/src/ServiceControl.Persistence.RavenDB/FailedMessageViewIndexNotifications.cs @@ -5,12 +5,12 @@ using System.Threading.Tasks; using Api; using Microsoft.Extensions.Hosting; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Persistence; using Persistence.RavenDB; using Raven.Client.Documents; - class FailedMessageViewIndexNotifications(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider) : IFailedMessageViewIndexNotifications + class FailedMessageViewIndexNotifications(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, ILogger logger) : IFailedMessageViewIndexNotifications , IDisposable , IHostedService { @@ -22,7 +22,7 @@ void OnNext() } catch (Exception ex) { - Logger.WarnFormat("Failed to emit MessageFailuresUpdated - {0}", ex); + logger.LogWarning(ex, "Failed to emit MessageFailuresUpdated"); } } @@ -87,8 +87,6 @@ public Task StopAsync(CancellationToken cancellationToken) return Task.CompletedTask; } - static readonly ILog Logger = LogManager.GetLogger(typeof(FailedMessageViewIndexNotifications)); - Func subscriber; IDisposable subscription; int lastUnresolvedCount; diff --git a/src/ServiceControl.Persistence.RavenDB/Infrastructure/Subscriptions/RavenSubscriptionStorage.cs b/src/ServiceControl.Persistence.RavenDB/Infrastructure/Subscriptions/RavenSubscriptionStorage.cs index fdf1520dd6..6b8218b753 100644 --- a/src/ServiceControl.Persistence.RavenDB/Infrastructure/Subscriptions/RavenSubscriptionStorage.cs +++ b/src/ServiceControl.Persistence.RavenDB/Infrastructure/Subscriptions/RavenSubscriptionStorage.cs @@ -7,9 +7,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; using NServiceBus; using NServiceBus.Extensibility; - using NServiceBus.Logging; using NServiceBus.Settings; using NServiceBus.Unicast.Subscriptions; using NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions; @@ -21,12 +21,12 @@ class RavenSubscriptionStorage : IServiceControlSubscriptionStorage { - public RavenSubscriptionStorage(IRavenSessionProvider sessionProvider, IReadOnlySettings settings, ReceiveAddresses receiveAddresses) : - this(sessionProvider, settings.EndpointName(), receiveAddresses.MainReceiveAddress, settings.GetAvailableTypes().Implementing().Select(e => new MessageType(e)).ToArray()) + public RavenSubscriptionStorage(IRavenSessionProvider sessionProvider, IReadOnlySettings settings, ReceiveAddresses receiveAddresses, ILogger logger) : + this(sessionProvider, settings.EndpointName(), receiveAddresses.MainReceiveAddress, settings.GetAvailableTypes().Implementing().Select(e => new MessageType(e)).ToArray(), logger) { } - public RavenSubscriptionStorage(IRavenSessionProvider sessionProvider, string endpointName, string localAddress, MessageType[] locallyHandledEventTypes) + public RavenSubscriptionStorage(IRavenSessionProvider sessionProvider, string endpointName, string localAddress, MessageType[] locallyHandledEventTypes, ILogger logger) { this.sessionProvider = sessionProvider; localClient = new SubscriptionClient @@ -36,7 +36,7 @@ public RavenSubscriptionStorage(IRavenSessionProvider sessionProvider, string en }; this.locallyHandledEventTypes = locallyHandledEventTypes; - + this.logger = logger; subscriptions = new Subscriptions(); UpdateLookup(); } @@ -198,9 +198,9 @@ async Task SetSubscriptions(Subscriptions newSubscriptions) static Task LoadSubscriptions(IAsyncDocumentSession session) => session.LoadAsync(Subscriptions.SingleDocumentId); - static async Task MigrateSubscriptions(IAsyncDocumentSession session, SubscriptionClient localClient) + async Task MigrateSubscriptions(IAsyncDocumentSession session, SubscriptionClient localClient) { - Logger.Info("Migrating subscriptions to new format"); + logger.LogInformation("Migrating subscriptions to new format"); var subscriptions = new Subscriptions(); @@ -224,10 +224,8 @@ static async Task MigrateSubscriptions(IAsyncDocumentSession sess Subscriptions subscriptions; ILookup subscriptionsLookup; MessageType[] locallyHandledEventTypes; - + readonly ILogger logger; SemaphoreSlim subscriptionsLock = new SemaphoreSlim(1); - - static readonly ILog Logger = LogManager.GetLogger(); } class Subscriptions diff --git a/src/ServiceControl.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs b/src/ServiceControl.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs index f1971af65c..f0172acff7 100644 --- a/src/ServiceControl.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs +++ b/src/ServiceControl.Persistence.RavenDB/RavenEmbeddedPersistenceLifecycle.cs @@ -6,12 +6,12 @@ namespace ServiceControl.Persistence.RavenDB using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client.Documents; using Raven.Client.Exceptions.Database; using ServiceControl.RavenDB; - sealed class RavenEmbeddedPersistenceLifecycle(RavenPersisterSettings databaseConfiguration, IHostApplicationLifetime lifetime) + sealed class RavenEmbeddedPersistenceLifecycle(RavenPersisterSettings databaseConfiguration, IHostApplicationLifetime lifetime, ILogger logger) : IRavenPersistenceLifecycle, IRavenDocumentStoreProvider, IDisposable { public async ValueTask GetDocumentStore(CancellationToken cancellationToken = default) @@ -58,7 +58,7 @@ public async Task Initialize(CancellationToken cancellationToken) } catch (DatabaseLoadTimeoutException e) { - Log.Warn("Could not connect to database. Retrying in 500ms...", e); + logger.LogWarning(e, "Could not connect to database. Retrying in 500ms..."); await Task.Delay(500, cancellationToken); } } @@ -86,7 +86,5 @@ public void Dispose() IDocumentStore? documentStore; EmbeddedDatabase? database; readonly SemaphoreSlim initializeSemaphore = new(1, 1); - - static readonly ILog Log = LogManager.GetLogger(typeof(RavenEmbeddedPersistenceLifecycle)); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/ArchiveDocumentManager.cs b/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/ArchiveDocumentManager.cs index 46589133a4..c83e693141 100644 --- a/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/ArchiveDocumentManager.cs +++ b/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/ArchiveDocumentManager.cs @@ -5,14 +5,14 @@ using System.Linq; using System.Threading.Tasks; using MessageFailures; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Persistence.RavenDB; using Raven.Client.Documents; using Raven.Client.Documents.Commands.Batches; using Raven.Client.Documents.Operations; using Raven.Client.Documents.Session; - class ArchiveDocumentManager(ExpirationManager expirationManager) + class ArchiveDocumentManager(ExpirationManager expirationManager, ILogger logger) { public Task LoadArchiveOperation(IAsyncDocumentSession session, string groupId, ArchiveType archiveType) => session.LoadAsync(ArchiveOperation.MakeId(groupId, archiveType)); @@ -138,7 +138,7 @@ public async Task RemoveArchiveOperation(IRavenSessionProvider sessionProvider, session.Advanced.Defer(new DeleteCommandData(archiveOperation.Id, null)); await session.SaveChangesAsync(); - Logger.Info($"Removing ArchiveOperation {archiveOperation.Id} completed"); + logger.LogInformation("Removing ArchiveOperation {ArchiveOperationId} completed", archiveOperation.Id); } public class GroupDetails @@ -147,6 +147,5 @@ public class GroupDetails public int NumberOfMessagesInGroup { get; set; } } - static readonly ILog Logger = LogManager.GetLogger(); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/MessageArchiver.cs b/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/MessageArchiver.cs index caf8715282..64f722bbe2 100644 --- a/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/MessageArchiver.cs +++ b/src/ServiceControl.Persistence.RavenDB/Recoverability/Archiving/MessageArchiver.cs @@ -4,8 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; - using NServiceBus.Logging; - using Raven.Client.Documents; + using Microsoft.Extensions.Logging; using RavenDB; using ServiceControl.Infrastructure.DomainEvents; using ServiceControl.Persistence.Recoverability; @@ -17,15 +16,17 @@ public MessageArchiver( IRavenSessionProvider sessionProvider, OperationsManager operationsManager, IDomainEvents domainEvents, - ExpirationManager expirationManager + ExpirationManager expirationManager, + ILogger logger ) { this.sessionProvider = sessionProvider; this.domainEvents = domainEvents; this.expirationManager = expirationManager; + this.logger = logger; this.operationsManager = operationsManager; - archiveDocumentManager = new ArchiveDocumentManager(expirationManager); + archiveDocumentManager = new ArchiveDocumentManager(expirationManager, logger); archivingManager = new ArchivingManager(domainEvents, operationsManager); unarchiveDocumentManager = new UnarchiveDocumentManager(); @@ -34,7 +35,7 @@ ExpirationManager expirationManager public async Task ArchiveAllInGroup(string groupId) { - logger.Info($"Archiving of {groupId} started"); + logger.LogInformation("Archiving of {GroupId} started", groupId); ArchiveOperation archiveOperation; using (var session = await sessionProvider.OpenSession()) @@ -48,15 +49,15 @@ public async Task ArchiveAllInGroup(string groupId) var groupDetails = await archiveDocumentManager.GetGroupDetails(session, groupId); if (groupDetails.NumberOfMessagesInGroup == 0) { - logger.Warn($"No messages to archive in group {groupId}"); + logger.LogWarning("No messages to archive in group {GroupId}", groupId); return; } - logger.Info($"Splitting group {groupId} into batches"); + logger.LogInformation("Splitting group {GroupId} into batches", groupId); archiveOperation = await archiveDocumentManager.CreateArchiveOperation(session, groupId, ArchiveType.FailureGroup, groupDetails.NumberOfMessagesInGroup, groupDetails.GroupName, batchSize); await session.SaveChangesAsync(); - logger.Info($"Group {groupId} has been split into {archiveOperation.NumberOfBatches} batches"); + logger.LogInformation("Group {GroupId} has been split into {NumberOfBatches} batches", groupId, archiveOperation.NumberOfBatches); } } @@ -70,11 +71,11 @@ public async Task ArchiveAllInGroup(string groupId) if (nextBatch == null) { // We're only here in the case where Raven indexes are stale - logger.Warn($"Attempting to archive a batch ({archiveOperation.Id}/{archiveOperation.CurrentBatch}) which appears to already have been archived."); + logger.LogWarning("Attempting to archive a batch ({ArchiveOperationId}/{ArchiveOperationCurrentBatch}) which appears to already have been archived.", archiveOperation.Id, archiveOperation.CurrentBatch); } else { - logger.Info($"Archiving {nextBatch.DocumentIds.Count} messages from group {groupId} starting"); + logger.LogInformation("Archiving {MessageCount} messages from group {GroupId} starting", nextBatch.DocumentIds.Count, groupId); } archiveDocumentManager.ArchiveMessageGroupBatch(batchSession, nextBatch); @@ -98,17 +99,17 @@ await domainEvents.Raise(new FailedMessageGroupBatchArchived if (nextBatch != null) { - logger.Info($"Archiving of {nextBatch.DocumentIds.Count} messages from group {groupId} completed"); + logger.LogInformation("Archiving of {MessageCount} messages from group {GroupId} completed", nextBatch.DocumentIds.Count, groupId); } } } - logger.Info($"Archiving of group {groupId} is complete. Waiting for index updates."); + logger.LogInformation("Archiving of group {GroupId} is complete. Waiting for index updates.", groupId); await archivingManager.ArchiveOperationFinalizing(archiveOperation.RequestId, archiveOperation.ArchiveType); if (!await archiveDocumentManager.WaitForIndexUpdateOfArchiveOperation(sessionProvider, archiveOperation.RequestId, TimeSpan.FromMinutes(5)) ) { - logger.Warn($"Archiving group {groupId} completed but index not updated."); + logger.LogWarning("Archiving group {GroupId} completed but index not updated.", groupId); } await archivingManager.ArchiveOperationCompleted(archiveOperation.RequestId, archiveOperation.ArchiveType); @@ -121,12 +122,12 @@ await domainEvents.Raise(new FailedMessageGroupArchived MessagesCount = archiveOperation.TotalNumberOfMessages, }); - logger.Info($"Archiving of group {groupId} completed"); + logger.LogInformation("Archiving of group {GroupId} completed", groupId); } public async Task UnarchiveAllInGroup(string groupId) { - logger.Info($"Unarchiving of {groupId} started"); + logger.LogInformation("Unarchiving of {GroupId} started", groupId); UnarchiveOperation unarchiveOperation; using (var session = await sessionProvider.OpenSession()) @@ -140,16 +141,16 @@ public async Task UnarchiveAllInGroup(string groupId) var groupDetails = await unarchiveDocumentManager.GetGroupDetails(session, groupId); if (groupDetails.NumberOfMessagesInGroup == 0) { - logger.Warn($"No messages to unarchive in group {groupId}"); + logger.LogWarning("No messages to unarchive in group {GroupId}", groupId); return; } - logger.Info($"Splitting group {groupId} into batches"); + logger.LogInformation("Splitting group {GroupId} into batches", groupId); unarchiveOperation = await unarchiveDocumentManager.CreateUnarchiveOperation(session, groupId, ArchiveType.FailureGroup, groupDetails.NumberOfMessagesInGroup, groupDetails.GroupName, batchSize); await session.SaveChangesAsync(); - logger.Info($"Group {groupId} has been split into {unarchiveOperation.NumberOfBatches} batches"); + logger.LogInformation("Group {GroupId} has been split into {NumberOfBatches} batches", groupId, unarchiveOperation.NumberOfBatches); } } @@ -162,11 +163,11 @@ public async Task UnarchiveAllInGroup(string groupId) if (nextBatch == null) { // We're only here in the case where Raven indexes are stale - logger.Warn($"Attempting to unarchive a batch ({unarchiveOperation.Id}/{unarchiveOperation.CurrentBatch}) which appears to already have been archived."); + logger.LogWarning("Attempting to unarchive a batch ({UnarchiveOperationId}/{UnarchiveOperationCurrentBatch}) which appears to already have been archived.", unarchiveOperation.Id, unarchiveOperation.CurrentBatch); } else { - logger.Info($"Unarchiving {nextBatch.DocumentIds.Count} messages from group {groupId} starting"); + logger.LogInformation("Unarchiving {MessageCount} messages from group {GroupId} starting", nextBatch.DocumentIds.Count, groupId); } unarchiveDocumentManager.UnarchiveMessageGroupBatch(batchSession, nextBatch, expirationManager); @@ -190,19 +191,19 @@ await domainEvents.Raise(new FailedMessageGroupBatchUnarchived if (nextBatch != null) { - logger.Info($"Unarchiving of {nextBatch.DocumentIds.Count} messages from group {groupId} completed"); + logger.LogInformation("Unarchiving of {MessageCount} messages from group {GroupId} completed", nextBatch.DocumentIds.Count, groupId); } } - logger.Info($"Unarchiving of group {groupId} is complete. Waiting for index updates."); + logger.LogInformation("Unarchiving of group {GroupId} is complete. Waiting for index updates.", groupId); await unarchivingManager.UnarchiveOperationFinalizing(unarchiveOperation.RequestId, unarchiveOperation.ArchiveType); if (!await unarchiveDocumentManager.WaitForIndexUpdateOfUnarchiveOperation(sessionProvider, unarchiveOperation.RequestId, TimeSpan.FromMinutes(5)) ) { - logger.Warn($"Unarchiving group {groupId} completed but index not updated."); + logger.LogWarning("Unarchiving group {GroupId} completed but index not updated.", groupId); } - logger.Info($"Unarchiving of group {groupId} completed"); + logger.LogInformation("Unarchiving of group {GroupId} completed", groupId); await unarchivingManager.UnarchiveOperationCompleted(unarchiveOperation.RequestId, unarchiveOperation.ArchiveType); await unarchiveDocumentManager.RemoveUnarchiveOperation(sessionProvider, unarchiveOperation); @@ -239,7 +240,7 @@ public IEnumerable GetArchivalOperations() readonly ArchivingManager archivingManager; readonly UnarchiveDocumentManager unarchiveDocumentManager; readonly UnarchivingManager unarchivingManager; - static readonly ILog logger = LogManager.GetLogger(); + readonly ILogger logger; const int batchSize = 1000; } } diff --git a/src/ServiceControl.Persistence.RavenDB/RetryBatchesDataStore.cs b/src/ServiceControl.Persistence.RavenDB/RetryBatchesDataStore.cs index 3138d9b893..4d951b9354 100644 --- a/src/ServiceControl.Persistence.RavenDB/RetryBatchesDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/RetryBatchesDataStore.cs @@ -4,18 +4,16 @@ using System.Collections.Generic; using System.Threading.Tasks; using MessageFailures; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client.Documents.Commands; using Raven.Client.Documents.Commands.Batches; using Raven.Client.Documents.Operations; using Raven.Client.Exceptions; using ServiceControl.Recoverability; - class RetryBatchesDataStore(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, ExpirationManager expirationManager) + class RetryBatchesDataStore(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, ExpirationManager expirationManager, ILogger logger) : IRetryBatchesDataStore { - static readonly ILog Log = LogManager.GetLogger(typeof(RetryBatchesDataStore)); - public async Task CreateRetryBatchesManager() { var session = await sessionProvider.OpenSession(); @@ -32,7 +30,7 @@ public async Task RecordFailedStagingAttempt(IReadOnlyCollection { var failedMessageRetry = failedMessageRetriesById[failedMessage.Id]; - Log.Warn($"Attempt {1} of {maxStagingAttempts} to stage a retry message {failedMessage.UniqueMessageId} failed", e); + logger.LogWarning(e, "Attempt 1 of {MaxStagingAttempts} to stage a retry message {UniqueMessageId} failed", maxStagingAttempts, failedMessage.UniqueMessageId); commands[commandIndex] = new PatchCommandData(failedMessageRetry.Id, null, new PatchRequest { @@ -57,8 +55,8 @@ public async Task RecordFailedStagingAttempt(IReadOnlyCollection } catch (ConcurrencyException) { - Log.DebugFormat( - "Ignoring concurrency exception while incrementing staging attempt count for {0}", + logger.LogDebug( + "Ignoring concurrency exception while incrementing staging attempt count for {StagingId}", stagingId); } } @@ -75,7 +73,7 @@ public async Task IncrementAttemptCounter(FailedMessageRetry message) } catch (ConcurrencyException) { - Log.DebugFormat("Ignoring concurrency exception while incrementing staging attempt count for {0}", message.FailedMessageId); + logger.LogDebug("Ignoring concurrency exception while incrementing staging attempt count for {MessageId}", message.FailedMessageId); } } diff --git a/src/ServiceControl.Persistence.RavenDB/RetryDocumentDataStore.cs b/src/ServiceControl.Persistence.RavenDB/RetryDocumentDataStore.cs index 5d5270cc14..686b77df9f 100644 --- a/src/ServiceControl.Persistence.RavenDB/RetryDocumentDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/RetryDocumentDataStore.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Threading.Tasks; using MessageFailures; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Persistence.Infrastructure; using Raven.Client.Documents; using Raven.Client.Documents.Commands.Batches; @@ -15,7 +15,7 @@ using ServiceControl.MessageFailures.Api; using ServiceControl.Recoverability; - class RetryDocumentDataStore(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider) : IRetryDocumentDataStore + class RetryDocumentDataStore(IRavenSessionProvider sessionProvider, IRavenDocumentStoreProvider documentStoreProvider, ILogger logger) : IRetryDocumentDataStore { public async Task StageRetryByUniqueMessageIds(string batchDocumentId, string[] messageIds) { @@ -48,7 +48,7 @@ public async Task MoveBatchToStaging(string batchDocumentId) } catch (ConcurrencyException) { - Logger.DebugFormat("Ignoring concurrency exception while moving batch to staging {0}", batchDocumentId); + logger.LogDebug("Ignoring concurrency exception while moving batch to staging {BatchDocumentId}", batchDocumentId); } } @@ -202,7 +202,5 @@ public async Task QueryFailureGroupViewOnGroupId(string groupI .FirstOrDefaultAsync(x => x.Id == groupId); return group; } - - static readonly ILog Logger = LogManager.GetLogger(typeof(RetryDocumentDataStore)); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/SubscriptionPersisterTests.cs b/src/ServiceControl.Persistence.Tests.RavenDB/SubscriptionPersisterTests.cs index bf60c59a17..1a5b35664c 100644 --- a/src/ServiceControl.Persistence.Tests.RavenDB/SubscriptionPersisterTests.cs +++ b/src/ServiceControl.Persistence.Tests.RavenDB/SubscriptionPersisterTests.cs @@ -8,6 +8,7 @@ using NServiceBus.Unicast.Subscriptions; using NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions; using NUnit.Framework; + using ServiceControl.Infrastructure; using ServiceControl.Infrastructure.RavenDB.Subscriptions; [TestFixture] @@ -16,7 +17,7 @@ class SubscriptionPersisterTests : RavenPersistenceTestBase [Test] public async Task ShouldReturnSubscriptionsForOlderVersionsOfSameMessageType() { - var subscriptionPersister = new RavenSubscriptionStorage(SessionProvider, "NServiceBus.Routing.EndpointName", "TestEndpoint", []); + var subscriptionPersister = new RavenSubscriptionStorage(SessionProvider, "NServiceBus.Routing.EndpointName", "TestEndpoint", [], LoggerUtil.CreateStaticLogger()); var v1MessageType = new MessageType(typeof(SampleMessageType).FullName, new Version(1, 0, 0)); var v2MessageType = new MessageType(typeof(SampleMessageType).FullName, new Version(2, 0, 0)); @@ -37,7 +38,7 @@ public async Task ShouldReturnSubscriptionsForOlderVersionsOfSameMessageType() [Test] public async Task ShouldReturnSubscriptionsForNewerVersionsOfSameMessageType() { - var subscriptionPersister = new RavenSubscriptionStorage(SessionProvider, "NServiceBus.Routing.EndpointName", "TestEndpoint", []); + var subscriptionPersister = new RavenSubscriptionStorage(SessionProvider, "NServiceBus.Routing.EndpointName", "TestEndpoint", [], LoggerUtil.CreateStaticLogger()); var v1MessageType = new MessageType(typeof(SampleMessageType).FullName, new Version(1, 0, 0)); var v2MessageType = new MessageType(typeof(SampleMessageType).FullName, new Version(2, 0, 0)); diff --git a/src/ServiceControl.Persistence/PersistenceManifest.cs b/src/ServiceControl.Persistence/PersistenceManifest.cs index 0be97cafb6..df6f0941f6 100644 --- a/src/ServiceControl.Persistence/PersistenceManifest.cs +++ b/src/ServiceControl.Persistence/PersistenceManifest.cs @@ -5,7 +5,9 @@ using System.IO; using System.Linq; using System.Text.Json; + using Microsoft.Extensions.Logging; using NServiceBus.Logging; + using ServiceControl.Infrastructure; public class PersistenceManifest { @@ -68,7 +70,7 @@ static PersistenceManifestLibrary() } catch (Exception ex) { - logger.Warn($"Failed to load persistence manifests from {assemblyDirectory}", ex); + logger.LogWarning(ex, "Failed to load persistence manifests from {AssemblyDirectory}", assemblyDirectory); } try @@ -83,10 +85,10 @@ static PersistenceManifestLibrary() } catch (Exception ex) { - logger.Warn($"Failed to load persistence manifests from development locations", ex); + logger.LogWarning(ex, "Failed to load persistence manifests from development locations"); } - PersistenceManifests.ForEach(m => logger.Info($"Found persistence manifest for {m.DisplayName}")); + PersistenceManifests.ForEach(m => logger.LogInformation("Found persistence manifest for {ManifestDisplayName}", m.DisplayName)); } static string GetAssemblyDirectory() @@ -107,7 +109,7 @@ public static PersistenceManifest Find(string persistenceType) return persistenceManifest; } - static readonly ILog logger = LogManager.GetLogger(typeof(PersistenceManifestLibrary)); + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(typeof(PersistenceManifestLibrary)); } } diff --git a/src/ServiceControl.RavenDB/EmbeddedDatabase.cs b/src/ServiceControl.RavenDB/EmbeddedDatabase.cs index 590792fe20..e9fa10ea44 100644 --- a/src/ServiceControl.RavenDB/EmbeddedDatabase.cs +++ b/src/ServiceControl.RavenDB/EmbeddedDatabase.cs @@ -10,11 +10,12 @@ namespace ServiceControl.RavenDB using System.Threading.Tasks; using ByteSizeLib; using Microsoft.Extensions.Hosting; - using NServiceBus.Logging; + using Microsoft.Extensions.Logging; using Raven.Client.Documents; using Raven.Client.Documents.Conventions; using Raven.Client.ServerWide.Operations; using Raven.Embedded; + using ServiceControl.Infrastructure; using Sparrow.Logging; public sealed class EmbeddedDatabase : IDisposable @@ -67,7 +68,7 @@ public static EmbeddedDatabase Start(EmbeddedDatabaseConfiguration databaseConfi ); } - Logger.InfoFormat("Loading RavenDB license from {0}", licenseFileNameAndServerDirectory.LicenseFileName); + logger.LogInformation("Loading RavenDB license from {LicenseFileName}", licenseFileNameAndServerDirectory.LicenseFileName); var serverOptions = new ServerOptions { CommandLineArgs = @@ -119,12 +120,12 @@ void Start(ServerOptions serverOptions) shutdownCancellationToken.ThrowIfCancellationRequested(); - Logger.Info("Restarting RavenDB server process"); + logger.LogInformation("Restarting RavenDB server process"); await EmbeddedServer.Instance.RestartServerAsync(); restartRequired = false; - Logger.Info("RavenDB server process restarted successfully."); + logger.LogInformation("RavenDB server process restarted successfully."); } catch (OperationCanceledException) when (shutdownCancellationToken.IsCancellationRequested) { @@ -132,7 +133,7 @@ void Start(ServerOptions serverOptions) } catch (Exception e) { - Logger.Fatal($"RavenDB server restart failed. Restart will be retried in {delayBetweenRestarts}.", e); + logger.LogCritical(e, "RavenDB server restart failed. Restart will be retried in {RavenDelayBetweenRestarts}.", delayBetweenRestarts); } } }, CancellationToken.None); @@ -148,11 +149,11 @@ void OnServerProcessExited(object? sender, ServerProcessExitedEventArgs _) restartRequired = true; if (sender is Process process) { - Logger.Warn($"RavenDB server process exited unexpectedly with exitCode: {process.ExitCode}. Process will be restarted."); + logger.LogWarning("RavenDB server process exited unexpectedly with exitCode: {RavenExitCode}. Process will be restarted.", process.ExitCode); } else { - Logger.Warn($"RavenDB server process exited unexpectedly. Process will be restarted."); + logger.LogWarning("RavenDB server process exited unexpectedly. Process will be restarted."); } } @@ -187,7 +188,7 @@ public async Task DeleteDatabase(string dbName) public async Task Stop(CancellationToken cancellationToken) { - Logger.Debug("Stopping RavenDB server"); + logger.LogDebug("Stopping RavenDB server"); EmbeddedServer.Instance.ServerProcessExited -= OnServerProcessExited; await shutdownTokenSource.CancelAsync(); @@ -224,23 +225,23 @@ public async Task Stop(CancellationToken cancellationToken) { // We always want to try and kill the process, even when already cancelled processId = await EmbeddedServer.Instance.GetServerProcessIdAsync(CancellationToken.None); - Logger.WarnFormat("Killing RavenDB server PID {0} because host cancelled", processId); + logger.LogWarning("Killing RavenDB server PID {PID} because host cancelled", processId); using var ravenChildProcess = Process.GetProcessById(processId); ravenChildProcess.Kill(entireProcessTree: true); // Kill only signals - Logger.WarnFormat("Waiting for RavenDB server PID {0} to exit... ", processId); + logger.LogWarning("Waiting for RavenDB server PID {PID} to exit... ", processId); // When WaitForExitAsync returns, the process could still exist but in a frozen state to flush // memory mapped pages to storage. await ravenChildProcess.WaitForExitAsync(CancellationToken.None); } catch (Exception e) { - Logger.ErrorFormat("Failed to kill RavenDB server PID {0} shutdown\n{1}", processId, e); + logger.LogError(e, "Failed to kill RavenDB server PID {PID} shutdown", processId); } } serverOptions = null!; - Logger.Debug("Stopped RavenDB server"); + logger.LogDebug("Stopped RavenDB server"); } public void Dispose() @@ -262,9 +263,9 @@ public void Dispose() // Set GracefulShutdownTimeout to Zero and exit ASAP, under normal operation instance would already // have been allowed to gracefully stop during "Stop" method. serverOptions!.GracefulShutdownTimeout = TimeSpan.Zero; - Logger.Debug("Disposing RavenDB server"); + logger.LogDebug("Disposing RavenDB server"); EmbeddedServer.Instance.Dispose(); - Logger.Debug("Disposed RavenDB server"); + logger.LogDebug("Disposed RavenDB server"); } shutdownTokenSource.Dispose(); @@ -287,7 +288,7 @@ static void RecordStartup(EmbeddedDatabaseConfiguration configuration) RavenDB Logging Level: {configuration.LogsMode} -------------------------------------------------------------"; - Logger.Info(startupMessage); + logger.LogInformation(startupMessage); } static long DataSize(EmbeddedDatabaseConfiguration configuration) @@ -354,6 +355,6 @@ static long DirSize(DirectoryInfo d) ServerOptions? serverOptions; static TimeSpan delayBetweenRestarts = TimeSpan.FromSeconds(60); - static readonly ILog Logger = LogManager.GetLogger(); + static readonly ILogger logger = LoggerUtil.CreateStaticLogger(); } } From 6df6fd2aed397c3acea595fea38550e901daf36b Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Thu, 19 Jun 2025 13:05:53 +0800 Subject: [PATCH 23/27] cleanup remaining references to LogManager --- .../TestSupport/ServiceControlComponentRunner.cs | 7 ++++--- .../TestSupport/ServiceControlComponentRunner.cs | 7 ++++--- .../LoggingConfigurator.cs | 10 ++++++---- .../RavenDbLogLevelToLogsModeMapper.cs | 5 +---- .../TestSupport/ServiceControlComponentRunner.cs | 15 ++++++++++----- .../ServiceControl.Persistence.csproj | 1 + .../HostApplicationBuilderExtensions.cs | 8 ++------ 7 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index f1b3e58a01..8ac0a4454a 100644 --- a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -50,6 +50,7 @@ async Task InitializeServiceControl(ScenarioContext context) var logPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(logPath); var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace, defaultLevel: LogLevel.Debug, logPath: logPath); + LoggerUtil.ActiveLoggers = Loggers.Test; var settings = new Settings(transportToUse.TypeName, persistenceToUse.PersistenceType, loggingSettings, forwardErrorMessages: false, errorRetentionPeriod: TimeSpan.FromDays(10)) { @@ -65,9 +66,9 @@ async Task InitializeServiceControl(ScenarioContext context) { var headers = messageContext.Headers; var id = messageContext.NativeMessageId; - var log = NServiceBus.Logging.LogManager.GetLogger(); + var logger = LoggerUtil.CreateStaticLogger(loggingSettings.LogLevel); headers.TryGetValue(Headers.MessageId, out var originalMessageId); - log.Debug($"OnMessage for message '{id}'({originalMessageId ?? string.Empty})."); + logger.LogDebug("OnMessage for message '{MessageId}'({OriginalMessageId})", id, originalMessageId ?? string.Empty); //Do not filter out CC, SA and HB messages as they can't be stamped if (headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageTypes) @@ -86,7 +87,7 @@ async Task InitializeServiceControl(ScenarioContext context) var currentSession = context.TestRunId.ToString(); if (!headers.TryGetValue("SC.SessionID", out var session) || session != currentSession) { - log.Debug($"Discarding message '{id}'({originalMessageId ?? string.Empty}) because it's session id is '{session}' instead of '{currentSession}'."); + logger.LogDebug("Discarding message '{MessageId}'({OriginalMessageId}) because it's session id is '{SessionId}' instead of '{CurrentSessionId}'", id, originalMessageId ?? string.Empty, session, currentSession); return true; } diff --git a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 65e1b4752f..27ed1bfade 100644 --- a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -45,6 +45,7 @@ async Task InitializeServiceControl(ScenarioContext context) Directory.CreateDirectory(logPath); var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace, defaultLevel: LogLevel.Debug, logPath: logPath); + LoggerUtil.ActiveLoggers = Loggers.Test; settings = new Settings(transportToUse.TypeName, persistenceToUse.PersistenceType, loggingSettings) { @@ -56,9 +57,9 @@ async Task InitializeServiceControl(ScenarioContext context) { var id = messageContext.NativeMessageId; var headers = messageContext.Headers; - var log = LoggerUtil.CreateStaticLogger(); + var logger = LoggerUtil.CreateStaticLogger(loggingSettings.LogLevel); headers.TryGetValue(Headers.MessageId, out var originalMessageId); - log.LogDebug("OnMessage for message '{MessageId}'({OriginalMessageId}).", id, originalMessageId ?? string.Empty); + logger.LogDebug("OnMessage for message '{MessageId}'({OriginalMessageId}).", id, originalMessageId ?? string.Empty); //Do not filter out CC, SA and HB messages as they can't be stamped if (headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageTypes) @@ -77,7 +78,7 @@ async Task InitializeServiceControl(ScenarioContext context) var currentSession = context.TestRunId.ToString(); if (!headers.TryGetValue("SC.SessionID", out var session) || session != currentSession) { - log.LogDebug("Discarding message '{MessageId}'({OriginalMessageId}) because it's session id is '{SessionId}' instead of '{CurrentSessionId}'.", id, originalMessageId ?? string.Empty, session, currentSession); + logger.LogDebug("Discarding message '{MessageId}'({OriginalMessageId}) because it's session id is '{SessionId}' instead of '{CurrentSessionId}'.", id, originalMessageId ?? string.Empty, session, currentSession); return true; } diff --git a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs index 4845965394..848c6a3cf3 100644 --- a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs +++ b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs @@ -12,16 +12,19 @@ namespace ServiceControl.Infrastructure using LogManager = NServiceBus.Logging.LogManager; using LogLevel = NLog.LogLevel; - // TODO: Migrate from NLog to .NET logging public static class LoggingConfigurator { public static void ConfigureLogging(LoggingSettings loggingSettings) { - if (NLog.LogManager.Configuration != null) + //used for loggers outside of ServiceControl (i.e. transports and core) to use the logger factory defined here + LogManager.UseFactory(new ExtensionsLoggerFactory(LoggerFactory.Create(configure => configure.BuildLogger(loggingSettings.LogLevel)))); + + if (!LoggerUtil.IsLoggingTo(Loggers.NLog) || NLog.LogManager.Configuration != null) { return; } + //configure NLog var nlogConfig = new LoggingConfiguration(); var simpleLayout = new SimpleLayout("${longdate}|${processtime}|${threadid}|${level}|${logger}|${message}${onexception:|${exception:format=tostring}}"); @@ -76,8 +79,7 @@ public static void ConfigureLogging(LoggingSettings loggingSettings) NLog.LogManager.Configuration = nlogConfig; - LogManager.UseFactory(new ExtensionsLoggerFactory(LoggerFactory.Create(configure => configure.BuildLogger(loggingSettings.LogLevel)))); - + //using LogManager here rather than LoggerUtil.CreateStaticLogger since this is exclusive to NLog var logger = LogManager.GetLogger("LoggingConfiguration"); var logEventInfo = new LogEventInfo { TimeStamp = DateTime.UtcNow }; var loggingTo = AppEnvironment.RunningInContainer ? "console" : fileTarget.FileName.Render(logEventInfo); diff --git a/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs b/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs index 16a99ab8f3..d3316ba830 100644 --- a/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs +++ b/src/ServiceControl.Infrastructure/RavenDbLogLevelToLogsModeMapper.cs @@ -1,12 +1,9 @@ namespace ServiceControl { using Microsoft.Extensions.Logging; - using NServiceBus.Logging; public class RavenDbLogLevelToLogsModeMapper { - static readonly ILog Logger = LogManager.GetLogger(typeof(RavenDbLogLevelToLogsModeMapper)); - public static string Map(string ravenDbLogLevel, ILogger logger) { switch (ravenDbLogLevel.ToLower()) @@ -25,7 +22,7 @@ public static string Map(string ravenDbLogLevel, ILogger logger) case "operations": return "Operations"; default: - Logger.WarnFormat("Unknown log level '{0}', mapped to 'Operations'", ravenDbLogLevel); + logger.LogWarning("Unknown log level '{RavenDbLogLevel}', mapped to 'Operations'", ravenDbLogLevel); return "Operations"; } } diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index debc3ed629..63635fa2cf 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -13,11 +13,12 @@ namespace ServiceControl.Monitoring.AcceptanceTests.TestSupport using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + using Microsoft.Extensions.Logging; using Monitoring; using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; - using NServiceBus.Logging; + using ServiceControl.Infrastructure; class ServiceControlComponentRunner( ITransportIntegration transportToUse, @@ -33,15 +34,16 @@ class ServiceControlComponentRunner( async Task InitializeServiceControl(ScenarioContext context) { + LoggerUtil.ActiveLoggers = Loggers.Test; settings = new Settings(transportType: transportToUse.TypeName) { ConnectionString = transportToUse.ConnectionString, HttpHostName = "localhost", OnMessage = (id, headers, body, @continue) => { - var log = LogManager.GetLogger(); + var logger = LoggerUtil.CreateStaticLogger(); headers.TryGetValue(Headers.MessageId, out var originalMessageId); - log.Debug($"OnMessage for message '{id}'({originalMessageId ?? string.Empty})."); + logger.LogDebug("OnMessage for message '{MessageId}'({OriginalMessageId})", id, originalMessageId ?? string.Empty); //Do not filter out CC, SA and HB messages as they can't be stamped if (headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageTypes) @@ -60,7 +62,7 @@ async Task InitializeServiceControl(ScenarioContext context) var currentSession = context.TestRunId.ToString(); if (!headers.TryGetValue("SC.SessionID", out var session) || session != currentSession) { - log.Debug($"Discarding message '{id}'({originalMessageId ?? string.Empty}) because it's session id is '{session}' instead of '{currentSession}'."); + logger.LogDebug("Discarding message '{MessageId}'({OriginalMessageId}) because it's session id is '{SessionId}' instead of '{CurrentSessionId}'", id, originalMessageId ?? string.Empty, session, currentSession); return Task.CompletedTask; } @@ -91,12 +93,15 @@ async Task InitializeServiceControl(ScenarioContext context) // Force the DI container to run the dependency resolution check to verify all dependencies can be resolved EnvironmentName = Environments.Development }); + hostBuilder.Logging.ClearProviders(); + hostBuilder.Logging.BuildLogger(LogLevel.Information); + hostBuilder.AddServiceControlMonitoring((criticalErrorContext, cancellationToken) => { var logitem = new ScenarioContext.LogItem { Endpoint = settings.InstanceName, - Level = LogLevel.Fatal, + Level = NServiceBus.Logging.LogLevel.Fatal, LoggerName = $"{settings.InstanceName}.CriticalError", Message = $"{criticalErrorContext.Error}{Environment.NewLine}{criticalErrorContext.Exception}" }; diff --git a/src/ServiceControl.Persistence/ServiceControl.Persistence.csproj b/src/ServiceControl.Persistence/ServiceControl.Persistence.csproj index 050bcbec4b..1806eaf133 100644 --- a/src/ServiceControl.Persistence/ServiceControl.Persistence.csproj +++ b/src/ServiceControl.Persistence/ServiceControl.Persistence.csproj @@ -7,6 +7,7 @@ + diff --git a/src/ServiceControl/HostApplicationBuilderExtensions.cs b/src/ServiceControl/HostApplicationBuilderExtensions.cs index 25685e7623..14ee26a003 100644 --- a/src/ServiceControl/HostApplicationBuilderExtensions.cs +++ b/src/ServiceControl/HostApplicationBuilderExtensions.cs @@ -21,7 +21,6 @@ namespace Particular.ServiceControl using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting.WindowsServices; using Microsoft.Extensions.Logging; - using NLog.Extensions.Logging; using NServiceBus; using NServiceBus.Configuration.AdvancedExtensibility; using NServiceBus.Transport; @@ -42,11 +41,8 @@ public static void AddServiceControl(this IHostApplicationBuilder hostBuilder, S EventSourceCreator.Create(); } - var logging = hostBuilder.Logging; - logging.ClearProviders(); - //HINT: configuration used by NLog comes from LoggingConfigurator.cs - logging.AddNLog(); - logging.SetMinimumLevel(settings.LoggingSettings.LogLevel); + hostBuilder.Logging.ClearProviders(); + hostBuilder.Logging.BuildLogger(settings.LoggingSettings.LogLevel); var services = hostBuilder.Services; var transportSettings = settings.ToTransportSettings(); From e37e28256aaa93f20ac67398ec3e34aa6dddf979 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Thu, 19 Jun 2025 15:53:19 +0800 Subject: [PATCH 24/27] missing files from last checkin --- src/ServiceControl.Infrastructure/LoggerUtil.cs | 11 ++++++++--- .../TransportTestFixture.cs | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index f85bd6776a..c18a54afc1 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -19,17 +19,22 @@ public static class LoggerUtil { public static Loggers ActiveLoggers { private get; set; } = Loggers.None; + public static bool IsLoggingTo(Loggers logger) + { + return (logger & ActiveLoggers) == logger; + } + public static void BuildLogger(this ILoggingBuilder loggingBuilder, LogLevel level) { - if ((Loggers.Test & ActiveLoggers) == Loggers.Test) + if (IsLoggingTo(Loggers.Test)) { loggingBuilder.Services.AddSingleton(new TestContextProvider(level)); } - if ((Loggers.NLog & ActiveLoggers) == Loggers.NLog) + if (IsLoggingTo(Loggers.NLog)) { loggingBuilder.AddNLog(); } - if ((Loggers.Seq & ActiveLoggers) == Loggers.Seq) + if (IsLoggingTo(Loggers.Seq)) { loggingBuilder.AddSeq(); } diff --git a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs index 9ecf8f1725..7dd9d6ef5d 100644 --- a/src/ServiceControl.Transports.Tests/TransportTestFixture.cs +++ b/src/ServiceControl.Transports.Tests/TransportTestFixture.cs @@ -23,7 +23,7 @@ class TransportTestFixture [SetUp] public virtual async Task Setup() { - //TODO remove LogManager usage + //used for loggers outside of ServiceControl (i.e. transports and core) to use the logger factory defined here LogManager.UseFactory(new ExtensionsLoggerFactory(new TestContextAppenderFactory(Microsoft.Extensions.Logging.LogLevel.Warning))); LoggerUtil.ActiveLoggers = Loggers.Test; configuration = new TransportTestsConfiguration(); From 4485d7b1bb4b8d63efd3e0219a0e8b644b6fa97c Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Fri, 20 Jun 2025 10:13:02 +0800 Subject: [PATCH 25/27] fix different dependency version test failure --- src/Directory.Packages.props | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index dfd35a5f78..fd7e86d45d 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -24,6 +24,7 @@ + From 4b80ba321070de38e67b4ffdb8c19865cae393af Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Fri, 20 Jun 2025 10:13:36 +0800 Subject: [PATCH 26/27] move loggerutil setup before first static logger usage --- src/ServiceControl.Infrastructure/LoggingSettings.cs | 6 +++--- src/ServiceControl.Persistence/PersistenceManifest.cs | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ServiceControl.Infrastructure/LoggingSettings.cs b/src/ServiceControl.Infrastructure/LoggingSettings.cs index c48b27d889..ea8967bb00 100644 --- a/src/ServiceControl.Infrastructure/LoggingSettings.cs +++ b/src/ServiceControl.Infrastructure/LoggingSettings.cs @@ -11,9 +11,6 @@ public class LoggingSettings { public LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLevel = LogLevel.Information, string logPath = null) { - LogLevel = InitializeLogLevel(rootNamespace, defaultLevel); - LogPath = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); - var loggingProviders = (SettingsReader.Read(rootNamespace, loggingProvidersKey) ?? "").Split(","); var activeLoggers = Loggers.None; if (loggingProviders.Contains("NLog")) @@ -26,6 +23,9 @@ public LoggingSettings(SettingsRootNamespace rootNamespace, LogLevel defaultLeve } //this defaults to NLog because historically that was the default, and we don't want to break existing installs that don't have the config key to define loggingProviders LoggerUtil.ActiveLoggers = activeLoggers == Loggers.None ? Loggers.NLog : activeLoggers; + + LogLevel = InitializeLogLevel(rootNamespace, defaultLevel); + LogPath = SettingsReader.Read(rootNamespace, logPathKey, Environment.ExpandEnvironmentVariables(logPath ?? DefaultLogLocation())); } public LogLevel LogLevel { get; } diff --git a/src/ServiceControl.Persistence/PersistenceManifest.cs b/src/ServiceControl.Persistence/PersistenceManifest.cs index df6f0941f6..9279f6cdc6 100644 --- a/src/ServiceControl.Persistence/PersistenceManifest.cs +++ b/src/ServiceControl.Persistence/PersistenceManifest.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Text.Json; using Microsoft.Extensions.Logging; - using NServiceBus.Logging; using ServiceControl.Infrastructure; public class PersistenceManifest From 92b99b069de550516157c978556cf53f14cf3911 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Fri, 20 Jun 2025 10:52:07 +0800 Subject: [PATCH 27/27] fix different dependency version test failure --- src/Directory.Packages.props | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index fd7e86d45d..16035eade5 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -25,6 +25,7 @@ +