From 1dc6fb870d7fb81425fc52abf3dff1eb4673b503 Mon Sep 17 00:00:00 2001 From: Rhys Bevilaqua Date: Thu, 17 Sep 2026 16:09:48 +0800 Subject: [PATCH 1/4] Add roslyn analyser to warn about using DateTime.Now or DateTime.UtcNow instead of TimeProvider --- src/BannedSymbols.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/BannedSymbols.txt diff --git a/src/BannedSymbols.txt b/src/BannedSymbols.txt new file mode 100644 index 0000000000..cf16a2f6d5 --- /dev/null +++ b/src/BannedSymbols.txt @@ -0,0 +1,4 @@ +P:System.DateTime.Now;Use TimeProvider instead. +P:System.DateTime.UtcNow;Use TimeProvider instead. +P:System.DateTimeOffset.Now;Use TimeProvider instead. +P:System.DateTimeOffset.UtcNow;Use TimeProvider instead. From 311449d85a1956484471e57eb27f4375255671a6 Mon Sep 17 00:00:00 2001 From: Rhys Bevilaqua Date: Fri, 18 Sep 2026 12:35:22 +0800 Subject: [PATCH 2/4] Add analyser and eithre pragma or editorconfig ignore the existing DateTime.Now usages --- src/BannedSymbols.txt | 2 +- src/Custom.Build.props | 5 +++++ src/Directory.Packages.props | 1 + .../.editorconfig | 4 ++++ src/Particular.LicensingComponent.UnitTests/.editorconfig | 1 + src/Particular.LicensingComponent/.editorconfig | 4 ++++ src/ServiceControl.AcceptanceTesting/.editorconfig | 3 +++ .../.editorconfig | 4 ++++ src/ServiceControl.AcceptanceTests.RavenDB/.editorconfig | 1 + .../.editorconfig | 4 ++++ src/ServiceControl.AcceptanceTests/.editorconfig | 1 + .../.editorconfig | 1 + src/ServiceControl.Audit.AcceptanceTests/.editorconfig | 1 + .../.editorconfig | 4 ++++ .../.editorconfig | 4 ++++ .../.editorconfig | 1 + src/ServiceControl.Audit.Persistence.Tests/.editorconfig | 1 + src/ServiceControl.Audit.Persistence/.editorconfig | 4 ++++ src/ServiceControl.Audit.UnitTests/.editorconfig | 1 + src/ServiceControl.Audit/.editorconfig | 4 ++++ src/ServiceControl.Config.Tests/.editorconfig | 1 + src/ServiceControl.Infrastructure.Metrics/Counter.cs | 2 ++ src/ServiceControl.Infrastructure.Metrics/Meter.cs | 2 ++ src/ServiceControl.Infrastructure.Tests/.editorconfig | 1 + src/ServiceControl.Infrastructure/.editorconfig | 4 ++++ .../Auth/AuthorizationAuditLog.cs | 2 ++ .../Auth/MessageActionAuditLog.cs | 2 ++ src/ServiceControl.Infrastructure/LoggingConfigurator.cs | 2 ++ src/ServiceControl.LicenseManagement/.editorconfig | 3 +++ .../.editorconfig | 1 + src/ServiceControl.Monitoring.UnitTests/.editorconfig | 1 + src/ServiceControl.Monitoring/.editorconfig | 4 ++++ .../.editorconfig | 1 + src/ServiceControl.Persistence.RavenDB/.editorconfig | 4 ++++ .../CustomChecks/CheckRavenDBIndexLag.cs | 2 ++ .../.editorconfig | 1 + .../.editorconfig | 1 + .../.editorconfig | 1 + .../.editorconfig | 1 + src/ServiceControl.Persistence.Tests/.editorconfig | 1 + src/ServiceControl.Persistence/.editorconfig | 4 ++++ src/ServiceControl.Persistence/CustomCheckDetail.cs | 2 ++ src/ServiceControl.Persistence/FailureDetails.cs | 2 ++ src/ServiceControl.Persistence/ProcessedMessage.cs | 8 +++++--- src/ServiceControl.Transports.ASBS.Tests/.editorconfig | 1 + src/ServiceControl.Transports.ASBS/.editorconfig | 4 ++++ src/ServiceControl.Transports.ASQ.Tests/.editorconfig | 1 + src/ServiceControl.Transports.ASQ/.editorconfig | 4 ++++ src/ServiceControl.Transports.IBMMQ.Tests/.editorconfig | 4 ++++ src/ServiceControl.Transports.IBMMQ/.editorconfig | 4 ++++ src/ServiceControl.Transports.Learning/.editorconfig | 4 ++++ src/ServiceControl.Transports.Msmq.Tests/.editorconfig | 1 + .../.editorconfig | 1 + src/ServiceControl.Transports.PostgreSql/.editorconfig | 4 ++++ src/ServiceControl.Transports.RabbitMQ/.editorconfig | 4 ++++ .../.editorconfig | 1 + .../.editorconfig | 1 + .../.editorconfig | 1 + .../.editorconfig | 1 + src/ServiceControl.Transports.SQS.Tests/.editorconfig | 1 + src/ServiceControl.Transports.SQS/.editorconfig | 4 ++++ .../.editorconfig | 1 + src/ServiceControl.Transports.SqlServer/.editorconfig | 4 ++++ src/ServiceControl.Transports.Tests/.editorconfig | 1 + src/ServiceControl.UnitTests/.editorconfig | 1 + src/ServiceControl/.editorconfig | 4 ++++ .../.editorconfig | 3 ++- .../.editorconfig | 3 ++- src/TestHelper/.editorconfig | 3 ++- 69 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 src/ServiceControl.AcceptanceTests.PostgreSql/.editorconfig create mode 100644 src/ServiceControl.AcceptanceTests.SqlServer/.editorconfig create mode 100644 src/ServiceControl.Infrastructure/.editorconfig create mode 100644 src/ServiceControl.LicenseManagement/.editorconfig create mode 100644 src/ServiceControl.Transports.IBMMQ.Tests/.editorconfig create mode 100644 src/ServiceControl.Transports.IBMMQ/.editorconfig diff --git a/src/BannedSymbols.txt b/src/BannedSymbols.txt index cf16a2f6d5..41f352f586 100644 --- a/src/BannedSymbols.txt +++ b/src/BannedSymbols.txt @@ -1,4 +1,4 @@ P:System.DateTime.Now;Use TimeProvider instead. P:System.DateTime.UtcNow;Use TimeProvider instead. P:System.DateTimeOffset.Now;Use TimeProvider instead. -P:System.DateTimeOffset.UtcNow;Use TimeProvider instead. +P:System.DateTimeOffset.UtcNow;Use TimeProvider instead. \ No newline at end of file diff --git a/src/Custom.Build.props b/src/Custom.Build.props index 450f2d830e..634c60584d 100644 --- a/src/Custom.Build.props +++ b/src/Custom.Build.props @@ -31,6 +31,11 @@ + + + + + win-x64 linux-x64 diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 1a712572da..389c5ba316 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -22,6 +22,7 @@ + diff --git a/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig b/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig index 28e30f9f38..9ec901786e 100644 --- a/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig +++ b/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig @@ -9,3 +9,7 @@ dotnet_diagnostic.CA2007.severity = none dotnet_diagnostic.IDE0040.severity = none csharp_style_var_elsewhere = true:error + +[InMemoryLicensingDataStore.cs] +# Justification: Throughput is based on external clocks +dotnet_diagnostic.RS0030.severity = none diff --git a/src/Particular.LicensingComponent.UnitTests/.editorconfig b/src/Particular.LicensingComponent.UnitTests/.editorconfig index ca5ad8bd2e..af444b967a 100644 --- a/src/Particular.LicensingComponent.UnitTests/.editorconfig +++ b/src/Particular.LicensingComponent.UnitTests/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/Particular.LicensingComponent/.editorconfig b/src/Particular.LicensingComponent/.editorconfig index 423278de8e..a3a8c2fb81 100644 --- a/src/Particular.LicensingComponent/.editorconfig +++ b/src/Particular.LicensingComponent/.editorconfig @@ -12,3 +12,7 @@ dotnet_diagnostic.IDE0010.severity = suggestion csharp_style_var_elsewhere = true:error csharp_style_var_for_built_in_types = true:error + +[{AuditThroughputCollectorHostedService.cs,ThroughputCollector.cs}] +# Justification: Throughput collection periods are based on current calendar dates +dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.AcceptanceTesting/.editorconfig b/src/ServiceControl.AcceptanceTesting/.editorconfig index 196d6e44a8..561c79ee69 100644 --- a/src/ServiceControl.AcceptanceTesting/.editorconfig +++ b/src/ServiceControl.AcceptanceTesting/.editorconfig @@ -2,3 +2,6 @@ # Justification: Usage is from test projects dotnet_diagnostic.CA2007.severity = none + +# Justification: Usage is from test projects +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.AcceptanceTests.PostgreSql/.editorconfig b/src/ServiceControl.AcceptanceTests.PostgreSql/.editorconfig new file mode 100644 index 0000000000..57e1132478 --- /dev/null +++ b/src/ServiceControl.AcceptanceTests.PostgreSql/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# Justification: Test project +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/.editorconfig b/src/ServiceControl.AcceptanceTests.RavenDB/.editorconfig index 5f68a610b3..7edc26fc18 100644 --- a/src/ServiceControl.AcceptanceTests.RavenDB/.editorconfig +++ b/src/ServiceControl.AcceptanceTests.RavenDB/.editorconfig @@ -2,3 +2,4 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.AcceptanceTests.SqlServer/.editorconfig b/src/ServiceControl.AcceptanceTests.SqlServer/.editorconfig new file mode 100644 index 0000000000..57e1132478 --- /dev/null +++ b/src/ServiceControl.AcceptanceTests.SqlServer/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# Justification: Test project +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.AcceptanceTests/.editorconfig b/src/ServiceControl.AcceptanceTests/.editorconfig index da44eb13fb..39ba1ad3e6 100644 --- a/src/ServiceControl.AcceptanceTests/.editorconfig +++ b/src/ServiceControl.AcceptanceTests/.editorconfig @@ -4,3 +4,4 @@ dotnet_diagnostic.CA2007.severity = none dotnet_diagnostic.PS0013.severity = none dotnet_diagnostic.PS0018.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Audit.AcceptanceTests.RavenDB/.editorconfig b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/.editorconfig index ca5ad8bd2e..af444b967a 100644 --- a/src/ServiceControl.Audit.AcceptanceTests.RavenDB/.editorconfig +++ b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Audit.AcceptanceTests/.editorconfig b/src/ServiceControl.Audit.AcceptanceTests/.editorconfig index ca5ad8bd2e..21561fb5dd 100644 --- a/src/ServiceControl.Audit.AcceptanceTests/.editorconfig +++ b/src/ServiceControl.Audit.AcceptanceTests/.editorconfig @@ -3,3 +3,4 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none dotnet_diagnostic.PS0018.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig b/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig index ff993b49bb..871d2cafea 100644 --- a/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[InMemoryLicensingDataStore.cs] +# Justification: In-memory persistence timestamps mirror production wall-clock behavior +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig index ff993b49bb..0b8a96c730 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[{UnitOfWork/RavenAuditIngestionUnitOfWork.cs,CustomChecks/CheckRavenDBIndexLag.cs,RavenAuditDataStore.cs}] +# Justification: RavenDB retention, index lag, and date boundaries require current wall-clock time +dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/.editorconfig b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/.editorconfig index ca5ad8bd2e..af444b967a 100644 --- a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Audit.Persistence.Tests/.editorconfig b/src/ServiceControl.Audit.Persistence.Tests/.editorconfig index c11a245166..eb03abe90c 100644 --- a/src/ServiceControl.Audit.Persistence.Tests/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.Tests/.editorconfig @@ -2,6 +2,7 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none # Justification: Tests don't support cancellation and don't need to forward IMessageHandlerContext.CancellationToken diff --git a/src/ServiceControl.Audit.Persistence/.editorconfig b/src/ServiceControl.Audit.Persistence/.editorconfig index ff993b49bb..6dda35ece2 100644 --- a/src/ServiceControl.Audit.Persistence/.editorconfig +++ b/src/ServiceControl.Audit.Persistence/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[ProcessedMessage.cs] +# Justification: Missing message timestamps fall back to the current wall-clock time +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Audit.UnitTests/.editorconfig b/src/ServiceControl.Audit.UnitTests/.editorconfig index ca5ad8bd2e..af444b967a 100644 --- a/src/ServiceControl.Audit.UnitTests/.editorconfig +++ b/src/ServiceControl.Audit.UnitTests/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Audit/.editorconfig b/src/ServiceControl.Audit/.editorconfig index ff993b49bb..ec86010240 100644 --- a/src/ServiceControl.Audit/.editorconfig +++ b/src/ServiceControl.Audit/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[{DetectSuccessfulRetriesEnricher.cs,DetectNewEndpointsFromAuditImportsEnricher.cs}] +# Justification: Audit enrichment timestamps must reflect when events are processed +dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Config.Tests/.editorconfig b/src/ServiceControl.Config.Tests/.editorconfig index c5410d8c02..a30ae83695 100644 --- a/src/ServiceControl.Config.Tests/.editorconfig +++ b/src/ServiceControl.Config.Tests/.editorconfig @@ -2,6 +2,7 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none # Justification: Executable specifications intentionally assign properties after the # object initializer to mirror user interaction order (e.g. typing a name after load) diff --git a/src/ServiceControl.Infrastructure.Metrics/Counter.cs b/src/ServiceControl.Infrastructure.Metrics/Counter.cs index 81aca4bdde..48dca91157 100644 --- a/src/ServiceControl.Infrastructure.Metrics/Counter.cs +++ b/src/ServiceControl.Infrastructure.Metrics/Counter.cs @@ -20,7 +20,9 @@ internal Counter(string name, bool enabled) eventsPerSecond = new int[2]; movingAverage = new int[300]; movingAverageEpochs = new long[300]; +#pragma warning disable RS0030 // Do not use banned apis: metrics do not need to use external time provider epoch = DateTime.UtcNow.Minute; +#pragma warning restore RS0030 } public void Mark() diff --git a/src/ServiceControl.Infrastructure.Metrics/Meter.cs b/src/ServiceControl.Infrastructure.Metrics/Meter.cs index 5994efc56c..805c3a6754 100644 --- a/src/ServiceControl.Infrastructure.Metrics/Meter.cs +++ b/src/ServiceControl.Infrastructure.Metrics/Meter.cs @@ -26,7 +26,9 @@ internal Meter(string name, bool enabled, float scale = 1) movingAverageSums = new long[300]; movingAverageCounts = new long[300]; movingAverageEpochs = new long[300]; +#pragma warning disable RS0030 // Do not use banned apis: metrics do not need to use external time provider epoch = DateTime.UtcNow.Minute; +#pragma warning restore RS0030 } public Measurement Measure() => new Measurement(this, enabled); diff --git a/src/ServiceControl.Infrastructure.Tests/.editorconfig b/src/ServiceControl.Infrastructure.Tests/.editorconfig index 07eabf2b62..5e97f04868 100644 --- a/src/ServiceControl.Infrastructure.Tests/.editorconfig +++ b/src/ServiceControl.Infrastructure.Tests/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Infrastructure/.editorconfig b/src/ServiceControl.Infrastructure/.editorconfig new file mode 100644 index 0000000000..57e1132478 --- /dev/null +++ b/src/ServiceControl.Infrastructure/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# Justification: Test project +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Infrastructure/Auth/AuthorizationAuditLog.cs b/src/ServiceControl.Infrastructure/Auth/AuthorizationAuditLog.cs index 08be56f22b..4ebcf4391a 100644 --- a/src/ServiceControl.Infrastructure/Auth/AuthorizationAuditLog.cs +++ b/src/ServiceControl.Infrastructure/Auth/AuthorizationAuditLog.cs @@ -54,7 +54,9 @@ static string BuildEcsEvent(string subjectId, string subjectName, string permiss { var ecs = new Dictionary { +#pragma warning disable RS0030 // Do not use banned apis: logging should use real time ["@timestamp"] = DateTimeOffset.UtcNow.ToString("O"), +#pragma warning restore RS0030 ["ecs"] = new { version = EcsVersion }, ["event"] = new { diff --git a/src/ServiceControl.Infrastructure/Auth/MessageActionAuditLog.cs b/src/ServiceControl.Infrastructure/Auth/MessageActionAuditLog.cs index 48e6df9149..26ac60bd73 100644 --- a/src/ServiceControl.Infrastructure/Auth/MessageActionAuditLog.cs +++ b/src/ServiceControl.Infrastructure/Auth/MessageActionAuditLog.cs @@ -65,7 +65,9 @@ static string BuildEcsEvent(AuditUser user, MessageActionKind kind, string permi { var ecs = new Dictionary { +#pragma warning disable RS0030 // Do not use banned apis: logging should use real time ["@timestamp"] = DateTimeOffset.UtcNow.ToString("O"), +#pragma warning restore RS0030 ["ecs"] = new { version = AuthorizationAuditLog.EcsVersion }, ["event"] = new { diff --git a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs index 5e232163a0..dc818d903c 100644 --- a/src/ServiceControl.Infrastructure/LoggingConfigurator.cs +++ b/src/ServiceControl.Infrastructure/LoggingConfigurator.cs @@ -34,7 +34,9 @@ public static string ConfigureNLog(string logFileName, string logPath, LogLevel NLog.LogManager.Configuration = nlogConfig; +#pragma warning disable RS0030 // Do not use banned apis: logging should use real time var logEventInfo = new LogEventInfo { TimeStamp = DateTime.UtcNow }; +#pragma warning restore RS0030 var fileTarget = nlogConfig.FindTargetByName("file"); return AppEnvironment.RunningInContainer ? "console" : fileTarget.FileName.Render(logEventInfo); } diff --git a/src/ServiceControl.LicenseManagement/.editorconfig b/src/ServiceControl.LicenseManagement/.editorconfig new file mode 100644 index 0000000000..9aa85040a1 --- /dev/null +++ b/src/ServiceControl.LicenseManagement/.editorconfig @@ -0,0 +1,3 @@ +[LicenseDetails.cs] +# Justification: License expiry must be evaluated against current wall-clock time +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/.editorconfig b/src/ServiceControl.Monitoring.AcceptanceTests/.editorconfig index 5f68a610b3..7edc26fc18 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/.editorconfig +++ b/src/ServiceControl.Monitoring.AcceptanceTests/.editorconfig @@ -2,3 +2,4 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Monitoring.UnitTests/.editorconfig b/src/ServiceControl.Monitoring.UnitTests/.editorconfig index 9a87832189..893cb5a60e 100644 --- a/src/ServiceControl.Monitoring.UnitTests/.editorconfig +++ b/src/ServiceControl.Monitoring.UnitTests/.editorconfig @@ -2,5 +2,6 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none csharp_style_var_elsewhere = true:error csharp_style_var_for_built_in_types = true:error \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/.editorconfig b/src/ServiceControl.Monitoring/.editorconfig index aff82c0034..fba218e051 100644 --- a/src/ServiceControl.Monitoring/.editorconfig +++ b/src/ServiceControl.Monitoring/.editorconfig @@ -2,3 +2,7 @@ # Justification: Application synchronization contexts don't require ConfigureAwait(false) dotnet_diagnostic.CA2007.severity = none + +[{QueueLength/LegacyQueueLengthReportHandler.cs,Infrastructure/EndpointTracker.cs,Infrastructure/WebApi/CachingHttpHandler.cs,Infrastructure/ReportThroughputHostedService.cs,Infrastructure/Api/EndpointMetricsApi.cs}] +# Justification: Monitoring windows, cache headers, and activity timestamps require current wall-clock time +dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.MultiInstance.AcceptanceTests/.editorconfig b/src/ServiceControl.MultiInstance.AcceptanceTests/.editorconfig index da44eb13fb..605eb32585 100644 --- a/src/ServiceControl.MultiInstance.AcceptanceTests/.editorconfig +++ b/src/ServiceControl.MultiInstance.AcceptanceTests/.editorconfig @@ -2,5 +2,6 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0013.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Persistence.RavenDB/.editorconfig b/src/ServiceControl.Persistence.RavenDB/.editorconfig index ff993b49bb..ddd6807ca0 100644 --- a/src/ServiceControl.Persistence.RavenDB/.editorconfig +++ b/src/ServiceControl.Persistence.RavenDB/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[CustomChecks/CheckRavenDBIndexLag.cs] +# Justification: The server timestamp must be compared with the system clock +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs index 6cac66e4ef..7ca775281e 100644 --- a/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs +++ b/src/ServiceControl.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs @@ -39,8 +39,10 @@ int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) { if (indexStats.IsStale && indexStats.LastIndexingTime.HasValue) { +#pragma warning disable RS0030 // Machine clock on purpose: LastIndexingTime comes from the server, so an injected clock would give a meaningless lag. var indexLag = DateTime.UtcNow - indexStats.LastIndexingTime.Value; +#pragma warning restore RS0030 if (indexLag > IndexLagThresholdError) { diff --git a/src/ServiceControl.Persistence.Tests.InMemory/.editorconfig b/src/ServiceControl.Persistence.Tests.InMemory/.editorconfig index 21f570a928..4f78cb606c 100644 --- a/src/ServiceControl.Persistence.Tests.InMemory/.editorconfig +++ b/src/ServiceControl.Persistence.Tests.InMemory/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Persistence.Tests.PostgreSql/.editorconfig b/src/ServiceControl.Persistence.Tests.PostgreSql/.editorconfig index eddbd3cab7..425436e187 100644 --- a/src/ServiceControl.Persistence.Tests.PostgreSql/.editorconfig +++ b/src/ServiceControl.Persistence.Tests.PostgreSql/.editorconfig @@ -2,5 +2,6 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/.editorconfig b/src/ServiceControl.Persistence.Tests.RavenDB/.editorconfig index 21f570a928..4f78cb606c 100644 --- a/src/ServiceControl.Persistence.Tests.RavenDB/.editorconfig +++ b/src/ServiceControl.Persistence.Tests.RavenDB/.editorconfig @@ -2,4 +2,5 @@ # Justification: Test project dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Persistence.Tests.SqlServer/.editorconfig b/src/ServiceControl.Persistence.Tests.SqlServer/.editorconfig index eddbd3cab7..425436e187 100644 --- a/src/ServiceControl.Persistence.Tests.SqlServer/.editorconfig +++ b/src/ServiceControl.Persistence.Tests.SqlServer/.editorconfig @@ -2,5 +2,6 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.RS0030.severity = none dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.Persistence.Tests/.editorconfig b/src/ServiceControl.Persistence.Tests/.editorconfig index da44eb13fb..39ba1ad3e6 100644 --- a/src/ServiceControl.Persistence.Tests/.editorconfig +++ b/src/ServiceControl.Persistence.Tests/.editorconfig @@ -4,3 +4,4 @@ dotnet_diagnostic.CA2007.severity = none dotnet_diagnostic.PS0013.severity = none dotnet_diagnostic.PS0018.severity = none +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Persistence/.editorconfig b/src/ServiceControl.Persistence/.editorconfig index ff993b49bb..b0f438f27a 100644 --- a/src/ServiceControl.Persistence/.editorconfig +++ b/src/ServiceControl.Persistence/.editorconfig @@ -2,3 +2,7 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none + +[{CustomCheckDetail.cs,FailureDetails.cs,ProcessedMessage.cs}] +# Justification: These default and fallback timestamps intentionally use the system clock +dotnet_diagnostic.RS0030.severity = none diff --git a/src/ServiceControl.Persistence/CustomCheckDetail.cs b/src/ServiceControl.Persistence/CustomCheckDetail.cs index d340b280d7..c1d71dc1be 100644 --- a/src/ServiceControl.Persistence/CustomCheckDetail.cs +++ b/src/ServiceControl.Persistence/CustomCheckDetail.cs @@ -14,7 +14,9 @@ public class CustomCheckDetail { public CustomCheckDetail() { +#pragma warning disable RS0030 // Do not use banned apis: default field value does not need to use external time provider ReportedAt = DateTime.UtcNow; +#pragma warning restore RS0030 } public required EndpointDetails OriginatingEndpoint { get; set; } diff --git a/src/ServiceControl.Persistence/FailureDetails.cs b/src/ServiceControl.Persistence/FailureDetails.cs index d22afe3b27..d1b21274fe 100644 --- a/src/ServiceControl.Persistence/FailureDetails.cs +++ b/src/ServiceControl.Persistence/FailureDetails.cs @@ -6,7 +6,9 @@ public class FailureDetails { public FailureDetails() { +#pragma warning disable RS0030 // Do not use banned apis: default field value does not need to use external time provider TimeOfFailure = DateTime.UtcNow; +#pragma warning restore RS0030 } public required string AddressOfFailingEndpoint { get; set; } diff --git a/src/ServiceControl.Persistence/ProcessedMessage.cs b/src/ServiceControl.Persistence/ProcessedMessage.cs index 63e0557cb5..2b0a33c2da 100644 --- a/src/ServiceControl.Persistence/ProcessedMessage.cs +++ b/src/ServiceControl.Persistence/ProcessedMessage.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using NServiceBus; - using ServiceControl.Persistence; using ServiceControl.Persistence.Infrastructure; public class ProcessedMessage @@ -20,8 +19,11 @@ public ProcessedMessage(Dictionary headers, Dictionary Date: Fri, 18 Sep 2026 12:41:48 +0800 Subject: [PATCH 3/4] Exclude another DateTime.Now error --- src/Custom.Build.props | 3 ++- src/ServiceControl.Config/UI/Shell/ShellViewModel.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Custom.Build.props b/src/Custom.Build.props index 634c60584d..5b108e52e7 100644 --- a/src/Custom.Build.props +++ b/src/Custom.Build.props @@ -31,7 +31,8 @@ - + + diff --git a/src/ServiceControl.Config/UI/Shell/ShellViewModel.cs b/src/ServiceControl.Config/UI/Shell/ShellViewModel.cs index 658c3c7984..d711caadf3 100644 --- a/src/ServiceControl.Config/UI/Shell/ShellViewModel.cs +++ b/src/ServiceControl.Config/UI/Shell/ShellViewModel.cs @@ -35,7 +35,9 @@ IEventAggregator eventAggregator DisplayName = "ServiceControl Config"; IsModal = false; LoadAppVersion(); +#pragma warning disable RS0030 // Do not use banned apis: UtcNow for copyright is acceptable CopyrightInfo = $"{DateTime.UtcNow.Year} © Particular Software"; +#pragma warning restore RS0030 RefreshInstancesCmd = Command.Create(async () => { From 205e19bbb2b62917b3f8dfb93b2d1c5411f86c15 Mon Sep 17 00:00:00 2001 From: Rhys Bevilaqua Date: Wed, 23 Sep 2026 12:49:41 +0800 Subject: [PATCH 4/4] change to explicit pragma ignores instead of excluding files --- .../.editorconfig | 6 +----- .../InMemoryLicensingDataStore.cs | 6 ++++++ src/Particular.LicensingComponent/.editorconfig | 6 +----- .../AuditThroughputCollectorHostedService.cs | 2 ++ .../ThroughputCollector.cs | 2 ++ .../.editorconfig | 6 +----- .../.editorconfig | 6 +----- .../CustomChecks/CheckRavenDBIndexLag.cs | 2 ++ .../RavenAuditDataStore.cs | 4 ++++ .../UnitOfWork/RavenAuditIngestionUnitOfWork.cs | 2 ++ src/ServiceControl.Audit.Persistence/.editorconfig | 6 +----- .../ProcessedMessage.cs | 4 ++++ src/ServiceControl.Audit/.editorconfig | 6 +----- .../DetectNewEndpointsFromAuditImportsEnricher.cs | 2 ++ .../Recoverability/DetectSuccessfulRetriesEnricher.cs | 2 ++ src/ServiceControl.LicenseManagement/.editorconfig | 4 +--- src/ServiceControl.LicenseManagement/LicenseDetails.cs | 6 ++++++ src/ServiceControl.Monitoring/.editorconfig | 6 +----- .../Infrastructure/Api/EndpointMetricsApi.cs | 10 ++++++++++ .../Infrastructure/EndpointTracker.cs | 2 ++ .../Infrastructure/ReportThroughputHostedService.cs | 2 ++ .../Infrastructure/WebApi/CachingHttpHandler.cs | 2 ++ .../QueueLength/LegacyQueueLengthReportHandler.cs | 4 ++++ src/ServiceControl.Persistence.RavenDB/.editorconfig | 6 +----- src/ServiceControl.Persistence/.editorconfig | 6 +----- src/ServiceControl.Transports.ASBS/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.ASQ/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.IBMMQ/.editorconfig | 5 +---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.Learning/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.PostgreSql/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.RabbitMQ/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.SQS/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl.Transports.SqlServer/.editorconfig | 4 ---- .../QueueLengthProvider.cs | 2 ++ src/ServiceControl/.editorconfig | 6 +----- src/ServiceControl/CustomChecks/CustomChecksUpdated.cs | 2 ++ .../EventLog/EventLogMappingDefinition.cs | 2 ++ src/ServiceControl/Infrastructure/Api/RetentionApi.cs | 2 ++ src/ServiceControl/Licensing/ActiveLicense.cs | 2 ++ .../Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs | 2 ++ .../Monitoring/EndpointInstanceMonitor.cs | 6 ++++++ .../Monitoring/EndpointInstanceMonitoring.cs | 4 ++++ .../Monitoring/HeartbeatMonitoringHostedService.cs | 2 ++ .../SagaAudit/SagaAuditMisconfigurationCustomCheck.cs | 4 ++++ src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs | 4 ++++ 52 files changed, 110 insertions(+), 85 deletions(-) diff --git a/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig b/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig index 9ec901786e..320c6fad7c 100644 --- a/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig +++ b/src/Particular.LicensingComponent.Persistence.InMemory/.editorconfig @@ -8,8 +8,4 @@ dotnet_diagnostic.CA2007.severity = none # Justification: Rider displays an error to do with "Accessibility modifiers required (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0040)" dotnet_diagnostic.IDE0040.severity = none -csharp_style_var_elsewhere = true:error - -[InMemoryLicensingDataStore.cs] -# Justification: Throughput is based on external clocks -dotnet_diagnostic.RS0030.severity = none +csharp_style_var_elsewhere = true:error \ No newline at end of file diff --git a/src/Particular.LicensingComponent.Persistence.InMemory/InMemoryLicensingDataStore.cs b/src/Particular.LicensingComponent.Persistence.InMemory/InMemoryLicensingDataStore.cs index 257eef677a..cffb95ee0c 100644 --- a/src/Particular.LicensingComponent.Persistence.InMemory/InMemoryLicensingDataStore.cs +++ b/src/Particular.LicensingComponent.Persistence.InMemory/InMemoryLicensingDataStore.cs @@ -134,19 +134,25 @@ public async Task UpdateUserIndicatorOnEndpoints(List userI await Task.CompletedTask; } +#pragma warning disable RS0030 // Do not use banned apis: Throughput is based on external clocks public async Task IsThereThroughputForLastXDays(int days, CancellationToken cancellationToken = default) => await Task.FromResult( allThroughput.Any(endpointThroughput => endpointThroughput.Value.Any( t => t.Key >= DateOnly.FromDateTime(DateTime.UtcNow).AddDays(-days) && t.Key <= DateOnly.FromDateTime(DateTime.UtcNow).AddDays(-1)))); +#pragma warning restore RS0030 public async Task IsThereThroughputForLastXDaysForSource(int days, ThroughputSource throughputSource, bool includeToday, CancellationToken cancellationToken = default) { +#pragma warning disable RS0030 // Do not use banned apis: Throughput is based on external clocks var endDate = includeToday ? DateOnly.FromDateTime(DateTime.UtcNow) : DateOnly.FromDateTime(DateTime.UtcNow).AddDays(-1); +#pragma warning restore RS0030 return await Task.FromResult( allThroughput.Any( endpointThroughput => endpointThroughput.Key.ThroughputSource == throughputSource && +#pragma warning disable RS0030 // Do not use banned apis: Throughput is based on external clocks endpointThroughput.Value.Any(t => t.Key >= DateOnly.FromDateTime(DateTime.UtcNow).AddDays(-days) && t.Key <= endDate))); +#pragma warning restore RS0030 } List GetAllConnectedEndpoints(string name) => endpoints.Where(w => w.SanitizedName == name || w.Id.Name == name).ToList(); diff --git a/src/Particular.LicensingComponent/.editorconfig b/src/Particular.LicensingComponent/.editorconfig index a3a8c2fb81..f16f0e5105 100644 --- a/src/Particular.LicensingComponent/.editorconfig +++ b/src/Particular.LicensingComponent/.editorconfig @@ -11,8 +11,4 @@ dotnet_diagnostic.IDE0040.severity = none dotnet_diagnostic.IDE0010.severity = suggestion csharp_style_var_elsewhere = true:error -csharp_style_var_for_built_in_types = true:error - -[{AuditThroughputCollectorHostedService.cs,ThroughputCollector.cs}] -# Justification: Throughput collection periods are based on current calendar dates -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file +csharp_style_var_for_built_in_types = true:error \ No newline at end of file diff --git a/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs b/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs index 5b345182dd..5576bc4732 100644 --- a/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs +++ b/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs @@ -91,7 +91,9 @@ async Task GatherThroughput(CancellationToken cancellationToken) var missingAuditThroughput = auditCounts .Where(auditCount => auditCount.UtcDate > endpoint.LastCollectedDate && +#pragma warning disable RS0030 // Do not use banned apis: Throughput collection periods are based on current calendar dates auditCount.UtcDate < DateOnly.FromDateTime(DateTime.UtcNow)) +#pragma warning restore RS0030 .Select(auditCount => new EndpointDailyThroughput(auditCount.UtcDate, auditCount.Count)) .ToList(); diff --git a/src/Particular.LicensingComponent/ThroughputCollector.cs b/src/Particular.LicensingComponent/ThroughputCollector.cs index e0b718c7f2..de53105085 100644 --- a/src/Particular.LicensingComponent/ThroughputCollector.cs +++ b/src/Particular.LicensingComponent/ThroughputCollector.cs @@ -123,7 +123,9 @@ public async Task GenerateThroughputReport(string spVersion, DateT if (reportEndDate is null || reportEndDate == DateTime.MinValue) { +#pragma warning disable RS0030 // Do not use banned apis: Throughput collection periods are based on current calendar dates reportEndDate = DateTime.UtcNow.Date; +#pragma warning restore RS0030 } var queueThroughputs = new List(); diff --git a/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig b/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig index 871d2cafea..8d96183ebc 100644 --- a/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.InMemory/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[InMemoryLicensingDataStore.cs] -# Justification: In-memory persistence timestamps mirror production wall-clock behavior -dotnet_diagnostic.RS0030.severity = none +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig index 0b8a96c730..8d96183ebc 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[{UnitOfWork/RavenAuditIngestionUnitOfWork.cs,CustomChecks/CheckRavenDBIndexLag.cs,RavenAuditDataStore.cs}] -# Justification: RavenDB retention, index lag, and date boundaries require current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file +dotnet_diagnostic.CA2007.severity = none \ 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 7cd6d76321..3495503f10 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/CustomChecks/CheckRavenDBIndexLag.cs @@ -38,7 +38,9 @@ int CheckAndReportIndexesWithTooMuchIndexLag(IndexInformation[] indexes) { if (indexStats.IsStale && indexStats.LastIndexingTime.HasValue) { +#pragma warning disable RS0030 // Do not use banned apis: RavenDB retention, index lag, and date boundaries require current wall-clock time var indexLag = DateTime.UtcNow - indexStats.LastIndexingTime.Value; +#pragma warning restore RS0030 if (indexLag > IndexLagThresholdError) { diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs index 18e2aa7706..d391765727 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs @@ -146,7 +146,9 @@ public async Task>> QueryAuditCounts(string endpoi if (oldestMsg != null) { +#pragma warning disable RS0030 // Do not use banned apis: RavenDB retention, index lag, and date boundaries require current wall-clock time var endDate = DateTime.UtcNow.Date.AddDays(1); +#pragma warning restore RS0030 var oldestMsgDate = oldestMsg.ProcessedAt.ToUniversalTime().Date; var thirtyDays = endDate.AddDays(-30); @@ -181,7 +183,9 @@ public async Task>> QueryAuditCounts(string endpoi { results.Add(new AuditCount { +#pragma warning disable RS0030 // Do not use banned apis: RavenDB retention, index lag, and date boundaries require current wall-clock time UtcDate = DateTime.UtcNow.Date, +#pragma warning restore RS0030 Count = 0 }); } diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs b/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs index 664dd7020b..bb20bc501b 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs @@ -43,7 +43,9 @@ public async Task RecordProcessedMessage(ProcessedMessage processedMessage, Read MetadataAsDictionary GetExpirationMetadata() => new() { +#pragma warning disable RS0030 // Do not use banned apis: RavenDB retention, index lag, and date boundaries require current wall-clock time [Constants.Documents.Metadata.Expires] = DateTime.UtcNow.Add(auditRetentionPeriod) +#pragma warning restore RS0030 }; public Task RecordSagaSnapshot(SagaSnapshot sagaSnapshot, CancellationToken cancellationToken = default) diff --git a/src/ServiceControl.Audit.Persistence/.editorconfig b/src/ServiceControl.Audit.Persistence/.editorconfig index 6dda35ece2..8d96183ebc 100644 --- a/src/ServiceControl.Audit.Persistence/.editorconfig +++ b/src/ServiceControl.Audit.Persistence/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[ProcessedMessage.cs] -# Justification: Missing message timestamps fall back to the current wall-clock time -dotnet_diagnostic.RS0030.severity = none +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence/ProcessedMessage.cs b/src/ServiceControl.Audit.Persistence/ProcessedMessage.cs index 1082567ab9..2ec3815df7 100644 --- a/src/ServiceControl.Audit.Persistence/ProcessedMessage.cs +++ b/src/ServiceControl.Audit.Persistence/ProcessedMessage.cs @@ -22,14 +22,18 @@ public ProcessedMessage(Dictionary headers, Dictionary { +#pragma warning disable RS0030 // Do not use banned apis: Audit enrichment timestamps must reflect when events are processed ["ServiceControl.Retry.Successful"] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow), +#pragma warning restore RS0030 ["ServiceControl.Retry.UniqueMessageId"] = newRetryMessageId }, Array.Empty()); var ackOperation = new TransportOperation(ackMessage, new UnicastAddressTag(ackQueue)); diff --git a/src/ServiceControl.LicenseManagement/.editorconfig b/src/ServiceControl.LicenseManagement/.editorconfig index 9aa85040a1..d107cb07b1 100644 --- a/src/ServiceControl.LicenseManagement/.editorconfig +++ b/src/ServiceControl.LicenseManagement/.editorconfig @@ -1,3 +1 @@ -[LicenseDetails.cs] -# Justification: License expiry must be evaluated against current wall-clock time -dotnet_diagnostic.RS0030.severity = none +[*.cs] \ No newline at end of file diff --git a/src/ServiceControl.LicenseManagement/LicenseDetails.cs b/src/ServiceControl.LicenseManagement/LicenseDetails.cs index 11f6c23ddc..fed98f446d 100644 --- a/src/ServiceControl.LicenseManagement/LicenseDetails.cs +++ b/src/ServiceControl.LicenseManagement/LicenseDetails.cs @@ -58,7 +58,9 @@ public static LicenseDetails TrialExpired() return FromLicense(new License { LicenseType = "Trial", +#pragma warning disable RS0030 // Do not use banned apis: License expiry must be evaluated against current wall-clock time ExpirationDate = DateTime.UtcNow.Date.AddDays(-2), //HasLicenseDateExpired uses a grace period of 1 day +#pragma warning restore RS0030 IsExtendedTrial = false, ValidApplications = ["All"] }); @@ -74,7 +76,9 @@ internal static LicenseDetails FromLicense(License license) UpgradeProtectionExpiration = license.UpgradeProtectionExpiration, //If expiration date is greater that 50 years treat is as no expiration date ExpirationDate = license.ExpirationDate.HasValue +#pragma warning disable RS0030 // Do not use banned apis: License expiry must be evaluated against current wall-clock time ? license.ExpirationDate.Value > DateTime.UtcNow.AddYears(50) ? null : license.ExpirationDate +#pragma warning restore RS0030 : license.ExpirationDate, RegisteredTo = license.RegisteredTo, IsCommercialLicense = license.IsCommercialLicense, @@ -107,7 +111,9 @@ static bool HasLicenseDateExpired(DateTime licenseDate) oneDayGrace = licenseDate.AddDays(1); } +#pragma warning disable RS0030 // Do not use banned apis: License expiry must be evaluated against current wall-clock time return oneDayGrace < DateTime.UtcNow.Date; +#pragma warning restore RS0030 } } diff --git a/src/ServiceControl.Monitoring/.editorconfig b/src/ServiceControl.Monitoring/.editorconfig index fba218e051..7197c99ab9 100644 --- a/src/ServiceControl.Monitoring/.editorconfig +++ b/src/ServiceControl.Monitoring/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: Application synchronization contexts don't require ConfigureAwait(false) -dotnet_diagnostic.CA2007.severity = none - -[{QueueLength/LegacyQueueLengthReportHandler.cs,Infrastructure/EndpointTracker.cs,Infrastructure/WebApi/CachingHttpHandler.cs,Infrastructure/ReportThroughputHostedService.cs,Infrastructure/Api/EndpointMetricsApi.cs}] -# Justification: Monitoring windows, cache headers, and activity timestamps require current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Infrastructure/Api/EndpointMetricsApi.cs b/src/ServiceControl.Monitoring/Infrastructure/Api/EndpointMetricsApi.cs index c47223ab2e..f05179f4ec 100644 --- a/src/ServiceControl.Monitoring/Infrastructure/Api/EndpointMetricsApi.cs +++ b/src/ServiceControl.Monitoring/Infrastructure/Api/EndpointMetricsApi.cs @@ -21,7 +21,9 @@ public MonitoredEndpoint[] GetAllEndpointsMetrics(int? history = null) foreach (var metric in InstanceMetrics) { var store = metricByInstanceLookup[metric.StoreType]; +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var intervals = store.GetIntervals(period, DateTime.UtcNow).ToLookup(k => k.Id.EndpointName); +#pragma warning restore RS0030 foreach (var endpoint in endpoints) { @@ -34,7 +36,9 @@ public MonitoredEndpoint[] GetAllEndpointsMetrics(int? history = null) foreach (var metric in QueueMetrics) { var store = metricByQueueLookup[metric.StoreType]; +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var intervals = store.GetIntervals(period, DateTime.UtcNow).ToLookup(k => k.Id.EndpointName); +#pragma warning restore RS0030 foreach (var endpoint in endpoints) { @@ -65,7 +69,9 @@ public MonitoredEndpointDetails GetSingleEndpointMetrics(string endpointName, in foreach (var metric in InstanceMetrics) { var store = metricByInstanceLookup[metric.StoreType]; +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var intervals = store.GetIntervals(period, DateTime.UtcNow); +#pragma warning restore RS0030 var intervalsByEndpoint = intervals.ToLookup(k => k.Id.EndpointName); @@ -106,7 +112,9 @@ public MonitoredEndpointDetails GetSingleEndpointMetrics(string endpointName, in foreach (var metric in QueueMetrics) { var store = metricByQueueLookup[metric.StoreType]; +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var intervals = store.GetIntervals(period, DateTime.UtcNow); +#pragma warning restore RS0030 var intervalsByEndpoint = intervals.ToLookup(k => k.Id.EndpointName); @@ -138,7 +146,9 @@ public MonitoredEndpointDetails GetSingleEndpointMetrics(string endpointName, in foreach (var metric in MessageTypeMetrics) { var store = metricByMessageTypeLookup[metric.StoreType]; +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var intervals = store.GetIntervals(period, DateTime.UtcNow).ToLookup(k => k.Id); +#pragma warning restore RS0030 foreach (var messageType in messageTypes) { diff --git a/src/ServiceControl.Monitoring/Infrastructure/EndpointTracker.cs b/src/ServiceControl.Monitoring/Infrastructure/EndpointTracker.cs index 389e6fd3d6..b9b0d60d31 100644 --- a/src/ServiceControl.Monitoring/Infrastructure/EndpointTracker.cs +++ b/src/ServiceControl.Monitoring/Infrastructure/EndpointTracker.cs @@ -20,7 +20,9 @@ Task RecordEndpointInstanceId(IMessageHandlerContext context) var instanceId = EndpointInstanceId.From(context.MessageHeaders); endpointRegistry.Record(instanceId); +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time activityTracker.Record(instanceId, DateTime.UtcNow); +#pragma warning restore RS0030 return Task.CompletedTask; } diff --git a/src/ServiceControl.Monitoring/Infrastructure/ReportThroughputHostedService.cs b/src/ServiceControl.Monitoring/Infrastructure/ReportThroughputHostedService.cs index d2af476bea..c6a84e42dc 100644 --- a/src/ServiceControl.Monitoring/Infrastructure/ReportThroughputHostedService.cs +++ b/src/ServiceControl.Monitoring/Infrastructure/ReportThroughputHostedService.cs @@ -59,8 +59,10 @@ async Task ReportOnThroughput(string serviceControlThroughputDataQueue, Cancella { var throughputData = new RecordEndpointThroughputData { +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time EndDateTime = DateTime.UtcNow, StartDateTime = DateTime.UtcNow.AddMinutes(-ReportSendingIntervalInMinutes), +#pragma warning restore RS0030 EndpointThroughputData = new EndpointThroughputData[endpointData.Length] }; diff --git a/src/ServiceControl.Monitoring/Infrastructure/WebApi/CachingHttpHandler.cs b/src/ServiceControl.Monitoring/Infrastructure/WebApi/CachingHttpHandler.cs index 6d1abdb06e..6bbc7c6749 100644 --- a/src/ServiceControl.Monitoring/Infrastructure/WebApi/CachingHttpHandler.cs +++ b/src/ServiceControl.Monitoring/Infrastructure/WebApi/CachingHttpHandler.cs @@ -16,7 +16,9 @@ public void OnResultExecuting(ResultExecutingContext context) if (!response.Headers.ContainsKey("Last-Modified")) { +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time response.Headers["Last-Modified"] = DateTime.UtcNow.ToString("R"); +#pragma warning restore RS0030 } if (!response.Headers.ContainsKey("Cache-Control")) diff --git a/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs b/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs index 161009a410..2d625c1272 100644 --- a/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs +++ b/src/ServiceControl.Monitoring/QueueLength/LegacyQueueLengthReportHandler.cs @@ -28,7 +28,9 @@ public class LegacyQueueLengthEndpoints { public bool TryAdd(string id) { +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 if (Volatile.Read(ref lastCleanTicks) + cleanIntervalTicks < nowTicks) { @@ -41,7 +43,9 @@ public bool TryAdd(string id) } readonly ConcurrentDictionary registeredInstances = new ConcurrentDictionary(); +#pragma warning disable RS0030 // Do not use banned apis: Monitoring windows, cache headers, and activity timestamps require current wall-clock time long lastCleanTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 static readonly long cleanIntervalTicks = TimeSpan.FromHours(1).Ticks; } } diff --git a/src/ServiceControl.Persistence.RavenDB/.editorconfig b/src/ServiceControl.Persistence.RavenDB/.editorconfig index ddd6807ca0..8d96183ebc 100644 --- a/src/ServiceControl.Persistence.RavenDB/.editorconfig +++ b/src/ServiceControl.Persistence.RavenDB/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[CustomChecks/CheckRavenDBIndexLag.cs] -# Justification: The server timestamp must be compared with the system clock -dotnet_diagnostic.RS0030.severity = none +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Persistence/.editorconfig b/src/ServiceControl.Persistence/.editorconfig index b0f438f27a..8d96183ebc 100644 --- a/src/ServiceControl.Persistence/.editorconfig +++ b/src/ServiceControl.Persistence/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[{CustomCheckDetail.cs,FailureDetails.cs,ProcessedMessage.cs}] -# Justification: These default and fallback timestamps intentionally use the system clock -dotnet_diagnostic.RS0030.severity = none +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.ASBS/.editorconfig b/src/ServiceControl.Transports.ASBS/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.ASBS/.editorconfig +++ b/src/ServiceControl.Transports.ASBS/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs b/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs index 2538772c49..7c673f6c5c 100644 --- a/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.ASBS/QueueLengthProvider.cs @@ -99,7 +99,9 @@ void UpdateQueueLength(KeyValuePair monitoredEndpoint, IReadOnly { new QueueLengthEntry { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time DateTicks = DateTime.UtcNow.Ticks, +#pragma warning restore RS0030 Value = runtimeInfo.ActiveMessageCount } }; diff --git a/src/ServiceControl.Transports.ASQ/.editorconfig b/src/ServiceControl.Transports.ASQ/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.ASQ/.editorconfig +++ b/src/ServiceControl.Transports.ASQ/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs b/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs index 4a2b245798..f84a21c211 100644 --- a/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.ASQ/QueueLengthProvider.cs @@ -86,7 +86,9 @@ async Task FetchLength(QueueLengthValue queueLength, CancellationToken cancellat void UpdateQueueLengthStore() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var endpointQueueLengthPair in queueLengths) { diff --git a/src/ServiceControl.Transports.IBMMQ/.editorconfig b/src/ServiceControl.Transports.IBMMQ/.editorconfig index b72ba8b499..d107cb07b1 100644 --- a/src/ServiceControl.Transports.IBMMQ/.editorconfig +++ b/src/ServiceControl.Transports.IBMMQ/.editorconfig @@ -1,4 +1 @@ - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file +[*.cs] \ No newline at end of file diff --git a/src/ServiceControl.Transports.IBMMQ/QueueLengthProvider.cs b/src/ServiceControl.Transports.IBMMQ/QueueLengthProvider.cs index abea3c1ec5..40f3580d36 100644 --- a/src/ServiceControl.Transports.IBMMQ/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.IBMMQ/QueueLengthProvider.cs @@ -58,7 +58,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken = void UpdateQueueLengthStore() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var endpointQueuePair in endpointQueues) { diff --git a/src/ServiceControl.Transports.Learning/.editorconfig b/src/ServiceControl.Transports.Learning/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.Learning/.editorconfig +++ b/src/ServiceControl.Transports.Learning/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs b/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs index 345b402698..ed6ef641bb 100644 --- a/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.Learning/QueueLengthProvider.cs @@ -46,7 +46,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken = void UpdateStore(ILookup queueLengths) { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var now = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var kvp in endpointsHash) { var instance = kvp.Key; diff --git a/src/ServiceControl.Transports.PostgreSql/.editorconfig b/src/ServiceControl.Transports.PostgreSql/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.PostgreSql/.editorconfig +++ b/src/ServiceControl.Transports.PostgreSql/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs b/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs index a4f2f2cc74..664d023bf2 100644 --- a/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.PostgreSql/QueueLengthProvider.cs @@ -63,7 +63,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken = void UpdateQueueLengthStore() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var tableNamePair in tableNames) { diff --git a/src/ServiceControl.Transports.RabbitMQ/.editorconfig b/src/ServiceControl.Transports.RabbitMQ/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.RabbitMQ/.editorconfig +++ b/src/ServiceControl.Transports.RabbitMQ/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs b/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs index ef74db62e3..2f4272532a 100644 --- a/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.RabbitMQ/QueueLengthProvider.cs @@ -59,7 +59,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken = void UpdateQueueLengths() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var endpointQueuePair in endpointQueues) { diff --git a/src/ServiceControl.Transports.SQS/.editorconfig b/src/ServiceControl.Transports.SQS/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.SQS/.editorconfig +++ b/src/ServiceControl.Transports.SQS/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs b/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs index 0cc527497c..6958d9de21 100644 --- a/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.SQS/QueueLengthProvider.cs @@ -80,7 +80,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken = void UpdateQueueLengthStore() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var tableNamePair in queues) { diff --git a/src/ServiceControl.Transports.SqlServer/.editorconfig b/src/ServiceControl.Transports.SqlServer/.editorconfig index 7db8c37212..ff993b49bb 100644 --- a/src/ServiceControl.Transports.SqlServer/.editorconfig +++ b/src/ServiceControl.Transports.SqlServer/.editorconfig @@ -2,7 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -[QueueLengthProvider.cs] -# Justification: Queue-length samples must use the current wall-clock time -dotnet_diagnostic.RS0030.severity = none \ No newline at end of file diff --git a/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs b/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs index f108fd34d4..462f0272ad 100644 --- a/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs +++ b/src/ServiceControl.Transports.SqlServer/QueueLengthProvider.cs @@ -126,7 +126,9 @@ internal static TimeSpan NextDelay(TimeSpan current, TimeSpan baseDelay, TimeSpa void UpdateQueueLengthStore() { +#pragma warning disable RS0030 // Do not use banned apis: Queue-length samples must use the current wall-clock time var nowTicks = DateTime.UtcNow.Ticks; +#pragma warning restore RS0030 foreach (var tableNamePair in tableNames) { diff --git a/src/ServiceControl/.editorconfig b/src/ServiceControl/.editorconfig index 53ff5ff1c1..8d96183ebc 100644 --- a/src/ServiceControl/.editorconfig +++ b/src/ServiceControl/.editorconfig @@ -1,8 +1,4 @@ [*.cs] # Justification: ServiceControl app has no synchronization context -dotnet_diagnostic.CA2007.severity = none - -[{EventLog/EventLogMappingDefinition.cs,SagaAudit/SagaAuditMisconfigurationCustomCheck.cs,Monitoring/Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs,SagaAudit/SagaUpdatedHandler.cs,Licensing/ActiveLicense.cs,Infrastructure/Api/RetentionApi.cs,CustomChecks/CustomChecksUpdated.cs,Monitoring/EndpointInstanceMonitoring.cs,Monitoring/HeartbeatMonitoringHostedService.cs,Monitoring/EndpointInstanceMonitor.cs}] -# Justification: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time -dotnet_diagnostic.RS0030.severity = none +dotnet_diagnostic.CA2007.severity = none \ No newline at end of file diff --git a/src/ServiceControl/CustomChecks/CustomChecksUpdated.cs b/src/ServiceControl/CustomChecks/CustomChecksUpdated.cs index d4f45e9d70..6e3c34ef1a 100644 --- a/src/ServiceControl/CustomChecks/CustomChecksUpdated.cs +++ b/src/ServiceControl/CustomChecks/CustomChecksUpdated.cs @@ -7,7 +7,9 @@ public class CustomChecksUpdated : IDomainEvent { public CustomChecksUpdated() { +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time RaisedAt = DateTime.UtcNow; +#pragma warning restore RS0030 } public int Failed { get; set; } diff --git a/src/ServiceControl/EventLog/EventLogMappingDefinition.cs b/src/ServiceControl/EventLog/EventLogMappingDefinition.cs index c532b17289..0839a7fc7a 100644 --- a/src/ServiceControl/EventLog/EventLogMappingDefinition.cs +++ b/src/ServiceControl/EventLog/EventLogMappingDefinition.cs @@ -92,6 +92,8 @@ protected void Severity(Func severity) Func descriptionFunc = m => m.ToString(); Func severityFunc = arg => EventLog.Severity.Info; +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time Func raisedAtFunc = arg => DateTime.UtcNow; +#pragma warning restore RS0030 } } \ No newline at end of file diff --git a/src/ServiceControl/Infrastructure/Api/RetentionApi.cs b/src/ServiceControl/Infrastructure/Api/RetentionApi.cs index 44d3c6fa71..b7b5031cf2 100644 --- a/src/ServiceControl/Infrastructure/Api/RetentionApi.cs +++ b/src/ServiceControl/Infrastructure/Api/RetentionApi.cs @@ -87,7 +87,9 @@ static bool TryValidateCutoff(DateTime? supplied, out DateTime? validated, out s value = value.ToUniversalTime(); +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time if (value > DateTime.UtcNow) +#pragma warning restore RS0030 { validated = null; error = "Cutoffs must not be in the future."; diff --git a/src/ServiceControl/Licensing/ActiveLicense.cs b/src/ServiceControl/Licensing/ActiveLicense.cs index 2a064fbd2a..64addc47da 100644 --- a/src/ServiceControl/Licensing/ActiveLicense.cs +++ b/src/ServiceControl/Licensing/ActiveLicense.cs @@ -47,7 +47,9 @@ internal static async Task ValidateTrialLicense(LicenseDetails l } //If the trial end date in db has been tampered, invalidate the license +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time if (trialEndDateInDb > DateOnly.FromDateTime(DateTime.UtcNow).AddDays(MaxTrialPeriodInDays)) +#pragma warning restore RS0030 { return LicenseDetails.TrialExpired(); } diff --git a/src/ServiceControl/Monitoring/Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs b/src/ServiceControl/Monitoring/Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs index 6f2783d3b6..0ef7cb83b6 100644 --- a/src/ServiceControl/Monitoring/Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs +++ b/src/ServiceControl/Monitoring/Contracts/HeartbeatMonitoring/HeartbeatsUpdated.cs @@ -7,7 +7,9 @@ class HeartbeatsUpdated : IDomainEvent { public HeartbeatsUpdated() { +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time RaisedAt = DateTime.UtcNow; +#pragma warning restore RS0030 } public int Active { get; set; } diff --git a/src/ServiceControl/Monitoring/EndpointInstanceMonitor.cs b/src/ServiceControl/Monitoring/EndpointInstanceMonitor.cs index 5298b6a672..c3840c47c1 100644 --- a/src/ServiceControl/Monitoring/EndpointInstanceMonitor.cs +++ b/src/ServiceControl/Monitoring/EndpointInstanceMonitor.cs @@ -60,7 +60,9 @@ async Task RaiseStateChangeEvents(HeartbeatStatus newStatus, DateTime? latestTim await domainEvents.Raise(new HeartbeatingEndpointDetected { Endpoint = Convert(Id), +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time DetectedAt = latestTimestamp ?? DateTime.UtcNow +#pragma warning restore RS0030 }, cancellationToken); } else if (status == HeartbeatStatus.Dead && Monitored) @@ -68,7 +70,9 @@ await domainEvents.Raise(new HeartbeatingEndpointDetected await domainEvents.Raise(new EndpointHeartbeatRestored { Endpoint = Convert(Id), +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time RestoredAt = latestTimestamp ?? DateTime.UtcNow +#pragma warning restore RS0030 }, cancellationToken); } } @@ -77,7 +81,9 @@ await domainEvents.Raise(new EndpointHeartbeatRestored await domainEvents.Raise(new EndpointFailedToHeartbeat { Endpoint = Convert(Id), +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time DetectedAt = DateTime.UtcNow, +#pragma warning restore RS0030 LastReceivedAt = latestTimestamp ?? DateTime.MinValue }, cancellationToken); } diff --git a/src/ServiceControl/Monitoring/EndpointInstanceMonitoring.cs b/src/ServiceControl/Monitoring/EndpointInstanceMonitoring.cs index d53cb08be1..3684a36e99 100644 --- a/src/ServiceControl/Monitoring/EndpointInstanceMonitoring.cs +++ b/src/ServiceControl/Monitoring/EndpointInstanceMonitoring.cs @@ -59,7 +59,9 @@ public async Task EndpointDetected(EndpointDetails newEndpointDetails, Cancellat { await domainEvents.Raise(new EndpointDetected { +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time DetectedAt = DateTime.UtcNow, +#pragma warning restore RS0030 Endpoint = newEndpointDetails }, cancellationToken); } @@ -93,7 +95,9 @@ await domainEvents.Raise(new HeartbeatsUpdated { Active = stats.Active, Failing = stats.Failing, +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time RaisedAt = DateTime.UtcNow +#pragma warning restore RS0030 }, cancellationToken); previousStats = stats; } diff --git a/src/ServiceControl/Monitoring/HeartbeatMonitoringHostedService.cs b/src/ServiceControl/Monitoring/HeartbeatMonitoringHostedService.cs index 779a2fb46f..206e5c0bd8 100644 --- a/src/ServiceControl/Monitoring/HeartbeatMonitoringHostedService.cs +++ b/src/ServiceControl/Monitoring/HeartbeatMonitoringHostedService.cs @@ -39,7 +39,9 @@ public async Task StartAsync(CancellationToken cancellationToken = default) async Task CheckEndpoints(CancellationToken cancellationToken) { +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time var inactivityThreshold = DateTime.UtcNow - gracePeriod; +#pragma warning restore RS0030 logger.LogDebug("Monitoring Endpoint Instances. Inactivity Threshold = {InactivityThreshold}", inactivityThreshold); diff --git a/src/ServiceControl/SagaAudit/SagaAuditMisconfigurationCustomCheck.cs b/src/ServiceControl/SagaAudit/SagaAuditMisconfigurationCustomCheck.cs index 6ff3fbd20b..db4c6a1314 100644 --- a/src/ServiceControl/SagaAudit/SagaAuditMisconfigurationCustomCheck.cs +++ b/src/ServiceControl/SagaAudit/SagaAuditMisconfigurationCustomCheck.cs @@ -16,7 +16,9 @@ public override Task PerformCheck(CancellationToken cancellationTok { var details = lastMisconfiguredMessageDetails; +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time if (details is null || details.Value.OccurredAt < DateTime.UtcNow.AddMinutes(-5)) +#pragma warning restore RS0030 { return Task.FromResult(CheckResult.Pass); } @@ -36,7 +38,9 @@ public static void LogMisconfiguredMessage(IMessageHandlerContext context) readonly struct Details { +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time public readonly DateTime OccurredAt = DateTime.UtcNow; +#pragma warning restore RS0030 public readonly string? Endpoint; public Details(IMessageHandlerContext context) diff --git a/src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs b/src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs index 25f1f73096..c8829304fe 100644 --- a/src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs +++ b/src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs @@ -18,7 +18,9 @@ public async Task Handle(SagaUpdatedMessage message, IMessageHandlerContext cont { SagaAuditMisconfigurationCustomCheck.LogMisconfiguredMessage(context); +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time if (auditQueueName is null || nextAuditQueueNameRefresh < DateTime.UtcNow) +#pragma warning restore RS0030 { await RefreshAuditQueue(context.CancellationToken); } @@ -35,6 +37,7 @@ public async Task Handle(SagaUpdatedMessage message, IMessageHandlerContext cont await context.ForwardCurrentMessageTo(auditQueueName); } +#pragma warning disable RS0030 // Do not use banned apis: Runtime events, expiry checks, and monitoring thresholds require current wall-clock time async Task RefreshAuditQueue(CancellationToken cancellationToken) { if (nextAuditQueueNameRefresh > DateTime.UtcNow) @@ -74,6 +77,7 @@ async Task RefreshAuditQueue(CancellationToken cancellationToken) { semaphore.Release(); } +#pragma warning restore RS0030 } static string auditQueueName;