Skip to content

Commit ce2c5ef

Browse files
DavidBoikebording
andauthored
Report saga audit misconfigurations more prominently (#4523)
* Remove TODO, make warning an error * Add custom check to report misconfiguration more prominently to user * More to-the-point error message, including endpoint name * Custom check approval test * Tweak wording --------- Co-authored-by: Brandon Ording <[email protected]>
1 parent 9ed0eb6 commit ce2c5ef

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.CustomCheckDetails.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
Configuration: Saga Audit Configuration
12
Health: ServiceControl Primary Instance
23
Health: ServiceControl Remotes
34
ServiceControl Health: Error Message Ingestion

src/ServiceControl/CustomChecks/InternalCustomChecks/InternalCustomChecks.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using NServiceBus.CustomChecks;
88
using NServiceBus.Hosting;
99
using Operations;
10+
using SagaAudit;
1011
using ServiceBus.Management.Infrastructure.Settings;
1112

1213
static class InternalCustomChecks
@@ -16,6 +17,7 @@ public static IHostApplicationBuilder AddInternalCustomChecks(this IHostApplicat
1617
var services = hostBuilder.Services;
1718
services.AddCustomCheck<CriticalErrorCustomCheck>();
1819
services.AddCustomCheck<CheckRemotes>();
20+
services.AddCustomCheck<SagaAuditMisconfigurationCustomCheck>();
1921

2022
services.AddHostedService(provider => new InternalCustomChecksHostedService(
2123
provider.GetServices<ICustomCheck>().ToList(),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#nullable enable
2+
3+
namespace ServiceControl.SagaAudit;
4+
5+
using System;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using NServiceBus;
9+
using NServiceBus.CustomChecks;
10+
11+
class SagaAuditMisconfigurationCustomCheck() : CustomCheck("Saga Audit Configuration", "Configuration", TimeSpan.FromMinutes(5))
12+
{
13+
static Details? lastMisconfiguredMessageDetails;
14+
15+
public override Task<CheckResult> PerformCheck(CancellationToken cancellationToken = default)
16+
{
17+
var details = lastMisconfiguredMessageDetails;
18+
19+
if (details is null || details.Value.OccurredAt < DateTime.UtcNow.AddMinutes(-5))
20+
{
21+
return Task.FromResult(CheckResult.Pass);
22+
}
23+
24+
var endpointDescription = details.Value.Endpoint == null
25+
? "without an endpoint name header"
26+
: $"from endpoint '{details.Value.Endpoint}'";
27+
28+
var msg = $"At least one misconfigured endpoint was detected. A saga audit message {endpointDescription} was detected within the last 5 minutes.";
29+
return Task.FromResult(CheckResult.Failed(msg));
30+
}
31+
32+
public static void LogMisconfiguredMessage(IMessageHandlerContext context)
33+
{
34+
lastMisconfiguredMessageDetails = new Details(context);
35+
}
36+
37+
readonly struct Details
38+
{
39+
public readonly DateTime OccurredAt = DateTime.UtcNow;
40+
public readonly string? Endpoint;
41+
42+
public Details(IMessageHandlerContext context)
43+
{
44+
// ReplyToAddress is the only identifying header present in saga audit messages
45+
_ = context.MessageHeaders.TryGetValue(Headers.ReplyToAddress, out Endpoint);
46+
}
47+
}
48+
}

src/ServiceControl/SagaAudit/SagaUpdatedHandler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class SagaUpdatedHandler(IPlatformConnectionBuilder connectionBuilder)
1515
{
1616
public async Task Handle(SagaUpdatedMessage message, IMessageHandlerContext context)
1717
{
18+
SagaAuditMisconfigurationCustomCheck.LogMisconfiguredMessage(context);
19+
1820
if (auditQueueName is null || nextAuditQueueNameRefresh < DateTime.UtcNow)
1921
{
2022
await RefreshAuditQueue();
@@ -25,8 +27,8 @@ public async Task Handle(SagaUpdatedMessage message, IMessageHandlerContext cont
2527
throw new UnrecoverableException("Could not determine audit queue name to forward saga update message. This message can be replayed after the ServiceControl Audit remote instance is running and accessible.");
2628
}
2729

28-
// TODO Forward saga audit messages and warn in ServiceControl 5, remove in 6
29-
log.WarnFormat("Configure the Saga Audit plugin to send messages to an audit instance. ServiceControl 6 will stop ingesting and forwarding Saga Audit to audit instances.");
30+
var endpointName = context.MessageHeaders.TryGetValue(Headers.ReplyToAddress, out var val) ? val : "(Unknown Endpoint)";
31+
log.ErrorFormat($"Received a saga audit message in the ServiceControl queue that should have been sent to the audit queue. This indicates that the endpoint '{endpointName}' using the SagaAudit plugin is misconfigured and should be changed to use the system's audit queue instead. The message has been forwarded to the audit queue, but this may not be possible in a future version of ServiceControl.");
3032
await context.ForwardCurrentMessageTo(auditQueueName);
3133
}
3234

0 commit comments

Comments
 (0)